spring ioc

72
Spring framework Motto: Musíte rozbít vejce když chcete udělat omeletu Spring framework training materials by Roman Pichlík is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License . 1 Sunday 13 May 2012

Upload: roman-pichlik

Post on 25-May-2015

796 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Spring ioc

Spring frameworkMotto: Musíte rozbít vejce když chcete udělat omeletu

Spring framework training materials by Roman Pichlík is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

1Sunday 13 May 2012

Page 2: Spring ioc

IoC containerZáklady

2Sunday 13 May 2012

Proč vzniknul SpringSpring koncepce a organizaceCo spring nabízí a k čemu jej můžete použít

Page 3: Spring ioc

Agenda

• IoC obecně

• Chrakteristika

• XML

• Anotace

• Pokročilé techniky

• Čeho se vyvarovat

3Sunday 13 May 2012

Page 4: Spring ioc

Cvičení

4Sunday 13 May 2012

Page 5: Spring ioc

• Příklad Rezervace knih

• Mějme rozhraní ReservationService, které slouží k rezervaci knih

• Mějme rozhraní BookStoreDao, které slouží k načítání informací o knihách

• Implementa ReservationService používá BookStoreDao pro čtení a ukládání knih z disku

• Existuje implementace FileSystemBookStoreDao

• Naimplementujte tyto třídy, aby prošel ReservationServiceTest

5Sunday 13 May 2012

- predpripraveny projekt sandbox- implementace BookService, knihy mohou byt v souboru viz trida Helper

Page 6: Spring ioc

Typický kód

public class ReservationServiceImpl implements ReservationService{ private BookStoreDao bookStoreDao;

public ReservationServiceImpl() { init(); }

private void init() { File dataDirectory = new File("/tmp/data"); bookStoreDao = new FileSystemBookStoreDao(dataDirectory); }

public boolean reserveBook(Long bookId) { Book book = bookStoreDao.getBook(bookId); //kod pro rezervaci vynechan }}

6Sunday 13 May 2012

Page 7: Spring ioc

Poznej svého nepřítelepublic class ReservationServiceImpl implements ReservationService{ private BookStoreDao bookStoreDao;

public ReservationServiceImpl() { init(); }

private void init() { File dataDirectory = new File("/tmp/data"); bookStoreDao = new FileSystemBookStoreDao(dataDirectory); }

public boolean reserveBook(Long bookId) { Book book = bookStoreDao.getBook(bookId); //kod pro rezervaci vynechan }}

1 cesta ve zdrojovém kódu

2 konkrétní implementace

7Sunday 13 May 2012

- konkretni implementace BookStore (WS, Database)- nutno vedet jakym zpusobem nainicializovat- cesta na tvrdo

Page 8: Spring ioc

Generalizace problému

• Kde najít

• Jak získat

• Jak zkonfigurovat

• Jak spojit dohromady

8Sunday 13 May 2012

- komponenty

Page 9: Spring ioc

Inversion of Control

9Sunday 13 May 2012

Page 10: Spring ioc

10Sunday 13 May 2012

Martin Fowler - Continuous Integration, Refactoring, Inversion of Control

Page 11: Spring ioc

Obrácená kontrola (řízení)

„…vychází z principu přenesení odpovědnosti za nalezení, konfiguraci a spojení komponent dohromady na

někoho třetího“11Sunday 13 May 2012

Page 12: Spring ioc

Dependency injection

12Sunday 13 May 2012

- komponenty nevi (nemusi pokud nechteji) o tom, ze je nekdo managuje- HOLLYWOOD princip

Page 13: Spring ioc

Service locator

13Sunday 13 May 2012

- komponenty si explicitne zadaji service locator

Page 14: Spring ioc

• Preferujte DI

• Žádné těsné vazby

• Transparentní

• No singleton hell

• Service locator

• body napojení

• Servlet/Controller aplikace

Service Locator vs. DI

14Sunday 13 May 2012

Page 15: Spring ioc

Zrefaktorujme Váš kód

15Sunday 13 May 2012

Page 16: Spring ioc

POJO

public class ReservationServiceImpl implements ReservationService{ private BookStoreDao bookStoreDao;

public ReservationServiceImpl() { }

public boolean reserveBook(Long bookId) { Book book = bookStoreDao.getBook(bookId); //kod pro rezervaci vynechan }}

16Sunday 13 May 2012

Page 17: Spring ioc

Metadata@Componentpublic class ReservationServiceImpl implements ReservationService{ @Autowired private BookStoreDao bookStoreDao;

public ReservationServiceImpl() { }

public boolean reserveBook(Long bookId) { Book book = bookStoreDao.getBook(bookId); //kod pro rezervaci vynechan return false; }}

@Componentpublic class FileSystemBookStoreDao implements BookStoreDao{

private File rootPath;

@Autowired public FileSystemBookStoreDao(File rootPath) { //kod vynechan }

}

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config/> <context:component-scan base-package="cz.sweb.pichlik.impl"/> <bean class="java.io.File"> <constructor-arg value="/mnt/data" /> </bean></beans>

17Sunday 13 May 2012

Page 18: Spring ioc

18Sunday 13 May 2012

Page 19: Spring ioc

Kontejner

19Sunday 13 May 2012

Page 20: Spring ioc

Test

20Sunday 13 May 2012

Page 21: Spring ioc

Benefity

• Indirekce == volné vazby

• Znovupoužitelnost

• Lepší testovatelnost

• Extensibilita

21Sunday 13 May 2012

- komponenty na sobe nezavisi primo, vetsi volnost pro obe strany kontraktu, nezavisle zmeny- komponenta v ruznem kontextu, testovani v izolaci- dvě možné impementace

Page 22: Spring ioc

IoC kontejner

22Sunday 13 May 2012

Page 23: Spring ioc

• Neinvazivnost

• Typy DI

• Metadata

• Reference mezi komponentami

• Řízení vzniku komponent

• Životní cyklus komponent

• Jednoduchá testovatelnost

23Sunday 13 May 2012

základní charakteristika Spring IoC kontejneru

Page 24: Spring ioc

Programy před zavedením IoC

24Sunday 13 May 2012

Page 25: Spring ioc

Programy po zavedení IoC

25Sunday 13 May 2012

Page 26: Spring ioc

• Bean == managovaný objekt

• POJO

• žádný marker interface

• final třídy

• param. konstruktory

Neinvazivnost

26Sunday 13 May 2012

Page 27: Spring ioc

Typy DI• Constructor injection

• + Bezpečnější, Přehlednější

• - Nepovinné závislosti

• - Cyklické závislosti

• Setter injection• + Nepovinné, velké množství závislosti

• - Chybějící závislosti

• Field injection• + jednoduchý zápis

• - netrasparentní27Sunday 13 May 2012

Pro ruzné situace se hodi různé typy DI

Page 28: Spring ioc

Metadata pro popis komponent

• Anotace• + Jednoduchý zápis

• - Zapečené v kódu

• XML• + Lze měnit v deploy time

• - Ukecané /

• Java kód• + Flexibilní, refactor friendly

• - Zapečené v kódu28Sunday 13 May 2012

- v aplikace obvykle zastoupeny oba dva typy

Page 29: Spring ioc

Reference mezi komponentami

• Typem

• Bezpečnější (teoreticky)

• Symbolickým jménem

• Více instancí stejného typu

• Variabilnější skládání

29Sunday 13 May 2012

Page 30: Spring ioc

Řízení vzniku komponent

• Uvnitř kontextu

• Delegace

• Factory, Factory method

• Mimo kontext

• Deserializace komponenty

• Web či ORM framework

30Sunday 13 May 2012

Legacy kod, 3rd party knihovny

Page 31: Spring ioc

XML

31Sunday 13 May 2012

Page 32: Spring ioc

Definice beany

• Jméno

• atribut id

• Typ

• atribut class

<bean id="" class=""></bean>

32Sunday 13 May 2012

- jeden typ Nkrát- jméno automaticky generovane- id hlidane parserem

Page 33: Spring ioc

Reference(závislosti)

• Elm. property/constructor-arg

• Hodnota (value)

• Reference (name)

<bean id="" class=""> <property name="" ref=""/> <property name="" value="" /> <constructor-arg ref="" value=""></constructor-arg></bean>

33Sunday 13 May 2012

- v pripade value -Property Editor- property/constructor-arg mozno kombinovat dohromady- ridi kontejner

Page 34: Spring ioc

java util collections

<bean> <property name="map"> <map> <entry key="" value=""></entry> <entry key-ref="" value-ref=""></entry> </map> </property> <property name="list"> <list> <value></value> <ref bean=""/> </list> </property></bean>

34Sunday 13 May 2012

- array, set

Page 35: Spring ioc

Good practice

• Jméno beany obsahuje jméno classy

• FooHooBar třída == fooHooBar beana

• Prefixujte jmena bean jejich typem či určením

• dao.FooHooBar, integration.FooHooBar

• V případě refaktoru názvu používejte alias

• Buďte defenzivní

• Inner beans

35Sunday 13 May 2012

Page 36: Spring ioc

36Sunday 13 May 2012

Page 37: Spring ioc

Méně ukecané XML

xmlns:p="http://www.springframework.org/schema/p"

<bean id="myBean" class="cz.sweb.MyBean" p:dependencyA-ref="dependencyA"/>

37Sunday 13 May 2012

Page 38: Spring ioc

Delegace vytváření instancí

• Factory

• Beana, která slouží k vyrábění jiných bean

• Factory method

• Beana se statickou metodou, která vyrábí instance sebe sama

38Sunday 13 May 2012

Page 39: Spring ioc

Factory

public class Factory { public MyBeanB newInstance() { return new MyBeanB(); }}

<bean id="factory" class="Factory" /> <bean id="beanB" factory-bean="factory" factory-method="newInstance" />

39Sunday 13 May 2012

Page 40: Spring ioc

Factory method<bean id="myBeanA" class="MyBeanA" factory-method="newInstance"/>

public class MyBeanA { public static MyBeanA newInstance() { return new MyBeanA(); }}

40Sunday 13 May 2012

- factory method musi byt staticka

Page 41: Spring ioc

Init, Destroy, Lazy atd.

import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;

public class Bean implements InitializingBean, DisposableBean{ public Bean() {} public void setDepedencies(String foo) {} public void afterPropertiesSet() throws Exception {}

public void myInit() {} public void destroy() throws Exception {} public void myDestroy(){}}

<bean class="Bean" init-method="myInit" destroy-method="myDestroy"> <property name="depedencies" value="foo" /></bean>

1

2

3

4

5

6

41Sunday 13 May 2012

- rozdilny lifecycle pro singleton a prototype

Page 42: Spring ioc

Poznámka na konto XML

• Občas ukecané Ale stále funkční ;-)

• Nejsilnější možnosti konfigurace

• DI (factory object|method delegation)

• Spring container customization

• Dědičnost

• Inner beany42Sunday 13 May 2012

ukecanost - DI, transaction demarcation

Page 43: Spring ioc

Praktické cvičení

43Sunday 13 May 2012

Page 44: Spring ioc

1.) Implementaci ReservationService a FileSystemBookStoreDao zaveďte jako beany v XML.2.) ReservationService dostane BookStoreDao implementaci (FileSystemBookStoreDao) skrze konstruktor3.) FileSystemBookStoreDao dostane cestu pro čtení a ukládání knih settrem4.) Připravte in-memory implementaci BookStoreDao (MemoryBookStoreDao), která bude číst/zapisovat do paměti resp. bude naimplementovaná nad java.util.Map<Long, Book>. Mapa bude obsahovat jako klíč Long a jako hodnotu Book. Mapu bude mozne nastavit do MemoryBookStoreDao settrem. Pripravte test, ktery overi, ze metody getBook a saveBook.5.) MemoryBookStoreDao bude mít init metodu, která vypíše předpřipravené knihy6.) MemoryBookStoreDao bude mít metodu destroy, která vyčistí mapu7.) Zaveďte jednu knihu jako inner beanu do java.util.Map<Long, Book>, ktera se pouzije pro konfiguraci beany MemoryBookStoreDao8.) Do tridy Book pridejte factory metodou newBook()9.) Upravte definici inner beany Book, aby se vytvarela factory metodou10.) Priprave Factory, ktera bude vytvaret java.util.Map<Long, Book> nahradte touto faktory puvodni beanu. Zachovejte vytvareni Book beany pres jeji factory metodu newBook().

V kazdem kroku validujte vas postup testem ReservationServiceTest, ktery musi prochazet.

44Sunday 13 May 2012

- pokracovat v sandboxu, odkomentovat dependence

Page 45: Spring ioc

import static org.hamcrest.CoreMatchers.*;import static org.junit.Assert.*;

import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath*:META-INF/<context-file-name>.xml"})public class MyTest {

@Autowired private MyBean bean; @Test public void testXXX() { }}

Jak otestovat

45Sunday 13 May 2012

Page 46: Spring ioc

Anotace

46Sunday 13 May 2012

Page 47: Spring ioc

Definice beany

• Základní anotace na třídě

• @Component

• @Controller

• @Service

• @Repository

• nepovinný atribut value (id)

47Sunday 13 May 2012

- component (genericka), controller (web), service (business logika), repository (DAO)- Repository, automaticky preklad vyjimek pokud pracujeme primo JDBC, Session atd.

Page 48: Spring ioc

Reference(závislosti)

• Základní anotace

• @Autowired

• field, metoda, konstruktor

• @Qualifier

• jemný výběr např. jménem

48Sunday 13 May 2012

- narozdil od XML a settrum moznost definovat na libovolne metode - @Autowired definuje required attribute pro volitelne zavislosti- @Autowired nelze pouzit pro injectovani generickych typu, @Resourc anotace musi byt pouzita namisto ni

Page 49: Spring ioc

@Componentpublic class Bean {

@Autowired(required=false) private OtherBean something; private final Hoo hoo; @Autowired public Bean(@Qualifier(value="hoo") Hoo hoo) { this.hoo = hoo; } @Autowired public void setX(String x) { }}

49Sunday 13 May 2012

Page 50: Spring ioc

Component scanning

• Stále potřebujeme XML

• Aktivace anotací

• Kde hledat anotované třídy

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config/> <context:component-scan base-package="cz.sweb.pichlik"/></beans>

50Sunday 13 May 2012

Page 51: Spring ioc

Autowiring

• Skládání objektů podle jejich závislostí

• @Autowired

• Řízený typem (volitelně jménem)

51Sunday 13 May 2012

- autowiring funguje rovnez v XML

Page 52: Spring ioc

Co je potřeba vzít v potaz

52Sunday 13 May 2012

- autowiring funguje typem by default

Page 53: Spring ioc

Předcházíme problémům

• Buďte defenzivní

• @Autowired + @Qualifier

• Použití specifičtějšího typu

53Sunday 13 May 2012

- pouziti specifickeho typu muze selhat ve chvili proxy modu napr. anotace

Page 54: Spring ioc

JSR 250 & JSR 330

• JSR 250

• @Resource , @PostConstruct, @PreDestroy

• JSR 330

• @Inject...

54Sunday 13 May 2012

JSR 250 - jediny zpusob jak definovat init metodu anotacemi

Page 55: Spring ioc

Poznámka na konto anotací

• + Méně ukecané • Definici beany

• Závislosti

• Transakce

• - pouze jedna instance od každé třídy

• - magické díky autowiringu

55Sunday 13 May 2012

Page 56: Spring ioc

Praktické cvičení

56Sunday 13 May 2012

Page 57: Spring ioc

1.) Beany ReservationService a MemoryBookStoreDao zavedte pomoci anotaci2.) Pouijte anotace pro volani init a destroy metody na MemoryBookStoreDao3.) java.util.Map<Long, Book> zavedte jmenem a pomoci anotace Resource (Autowired nebude fungovat)4.) Upravte definici ReservationService, aby se vzdy pouzila implementace MemoryBookStoreDao

V kazdem kroku validujte vas postup testem ReservationServiceTest, ktery musi prochazet.

57Sunday 13 May 2012

Page 58: Spring ioc

Pokročilá témata

58Sunday 13 May 2012

neznamená méně důležitá

Page 59: Spring ioc

Životní cyklus komponent

• Jedna instance komponenty

• Nová instance komponenty

• Konverzační instance komponenty

59Sunday 13 May 2012

Page 60: Spring ioc

Singleton

60Sunday 13 May 2012

Page 61: Spring ioc

Prototype

61Sunday 13 May 2012

Page 62: Spring ioc

Request, Session

Proxy Singleton

62Sunday 13 May 2012

- zmena scope je vzdy problem (singleton vs. scope)- http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-method-injection

Page 63: Spring ioc

Definice

• XML

• atribut scope

• Anotace

• @Scope(value="...")

63Sunday 13 May 2012

Page 64: Spring ioc

Praktické cvičení

64Sunday 13 May 2012

Page 65: Spring ioc

1.) Upravte definici beany Book, aby mela scope prototype2.) Upravte definici beany java.util.Map<Long, Book>, aby pod dvema ruznymi klici referencovala beanu Book3.) Pripravte test, ktery overi, ze List skutecne obsahuje ruzne instance beany Book4.) Zmente scope prototype na singleton5.) Overte testem, ze List obsahuje jednu a tu samou instanci objektu Book

65Sunday 13 May 2012

Page 66: Spring ioc

Java Config

66Sunday 13 May 2012

Page 67: Spring ioc

Java Based Config

• Mix anotací a Java kódu

• Alternativa k XML

• @Configuration

• @Bean

• name, init, destroy, autowire

• @Import

67Sunday 13 May 2012

- lze kombinovat XML, Anotace i Java Based config- vhodné pro případy kdy v XML máme pouze deployment specifické beany a zbytek chceme mít v kódu- k init, destroy lze používat jako alternativu JSR-250 anotace

Page 68: Spring ioc

public class MyService {

private final DaoInterface daoInterface;

public MyService(DaoInterface daoInterface) { super(); this.daoInterface = daoInterface; }}

<beans ...> <bean class="cz.sweb.pichlik.springioc.javaconfig.ConfigClass" />

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean></beans>

@Configurationpublic class ConfigClass {

@Autowired private DataSource dataSource;

@Bean() public MyService configureMyservice(){ return new MyService(configureJdbcDao()); }

@Bean() public JdbcDao configureJdbcDao() { return new JdbcDao(dataSource); }

@Bean() public HibernateDao configureHiberDao() { return new HibernateDao(dataSource); }}

definice beany

zavedení configu

dependency injection

68Sunday 13 May 2012

autowiring funguje viz DataSource beana

Page 69: Spring ioc

Jak to funguje• JavaConfig třídy jsou

dynamicky rozšířeny

• CGLIB

• volání configureJdbcDao jde přes proxy IoC kontejneru

• scopes

• postprocessing

• autowiring

@Configurationpublic class ConfigClass {

@Autowired private DataSource dataSource;

@Bean() public MyService configureMyservice(){ return new MyService(configureJdbcDao()); }

@Bean() public JdbcDao configureJdbcDao() { return new JdbcDao(dataSource); }

@Bean() public HibernateDao configureHiberDao() { return new HibernateDao(dataSource); }}

69Sunday 13 May 2012

Page 70: Spring ioc

Zavedení JavaConfig tříd

• Třídy anotované @Configuration

• Tři způsoby zavedení JavaConfigu

• Klasická beana v XML

• Beana na scanované classpath

• Programově• new AnnotationConfigApplicationContext(ConfigClass.class)

70Sunday 13 May 2012

Page 71: Spring ioc

Praktické cvičení

71Sunday 13 May 2012

Page 72: Spring ioc

1.) Pripravte JavaConfig beanu pomoci anotaci, ktery bude zavadet beanu MemoryBookStoreDao. Z tridy MemoryBookStoreDao odstrante vsechny anotace.2.) Zajistete deklarativne volani (nevolejte primo) init a destroy metody na MemoryBookStoreDao3.) Beanu reprezentujici java.util.Map<Long, Book> si nechte nainjectovat do bean JavaConfig pres setter

V kazdem kroku validujte vas postup testem ReservationServiceTest, ktery musi prochazet.

72Sunday 13 May 2012