Spring ioc

1,075 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,075
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
15
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Spring ioc

  1. 1. 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.Sunday 13 May 2012 1
  2. 2. IoC container ZákladySunday 13 May 2012 2Proč vzniknul SpringSpring koncepce a organizaceCo spring nabízí a k čemu jej můžete použít
  3. 3. Agenda • IoC obecně • Chrakteristika • XML • Anotace • Pokročilé techniky • Čeho se vyvarovatSunday 13 May 2012 3
  4. 4. CvičeníSunday 13 May 2012 4
  5. 5. • 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 ReservationServiceTestSunday 13 May 2012 5- predpripraveny projekt sandbox- implementace BookService, knihy mohou byt v souboru viz trida Helper
  6. 6. 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 } }Sunday 13 May 2012 6
  7. 7. Poznej svého nepřítele public class ReservationServiceImpl implements ReservationService{ private BookStoreDao bookStoreDao; public ReservationServiceImpl() { } init(); 1 cesta ve zdrojovém kódu private void init() { File dataDirectory = new File("/tmp/data"); bookStoreDao = new FileSystemBookStoreDao(dataDirectory); } public boolean reserveBook(Long bookId) { Book book = bookStoreDao.getBook(bookId); 2 konkrétní implementace //kod pro rezervaci vynechan } }Sunday 13 May 2012 7- konkretni implementace BookStore (WS, Database)- nutno vedet jakym zpusobem nainicializovat- cesta na tvrdo
  8. 8. Generalizace problému • Kde najít • Jak získat • Jak zkonfigurovat • Jak spojit dohromadySunday 13 May 2012 8- komponenty
  9. 9. Inversion of ControlSunday 13 May 2012 9
  10. 10. Sunday 13 May 2012 10Martin Fowler - Continuous Integration, Refactoring, Inversion of Control
  11. 11. 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“Sunday 13 May 2012 11
  12. 12. Dependency injectionSunday 13 May 2012 12- komponenty nevi (nemusi pokud nechteji) o tom, ze je nekdo managuje- HOLLYWOOD princip
  13. 13. Service locatorSunday 13 May 2012 13- komponenty si explicitne zadaji service locator
  14. 14. Service Locator vs. DI • Preferujte DI • Žádné těsné vazby • Transparentní • No singleton hell • Service locator • body napojení • Servlet/Controller aplikaceSunday 13 May 2012 14
  15. 15. Zrefaktorujme Váš kódSunday 13 May 2012 15
  16. 16. 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 } }Sunday 13 May 2012 16
  17. 17. Metadata @Component @Component public class ReservationServiceImpl implements public class FileSystemBookStoreDao implements BookStoreDao{ ReservationService{ @Autowired private File rootPath; private BookStoreDao bookStoreDao; @Autowired public ReservationServiceImpl() { public FileSystemBookStoreDao(File rootPath) { } //kod vynechan } public boolean reserveBook(Long bookId) { Book book = bookStoreDao.getBook(bookId); } //kod pro rezervaci vynechan return false; } } <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>Sunday 13 May 2012 17
  18. 18. Sunday 13 May 2012 18
  19. 19. KontejnerSunday 13 May 2012 19
  20. 20. TestSunday 13 May 2012 20
  21. 21. Benefity • Indirekce == volné vazby • Znovupoužitelnost • Lepší testovatelnost • ExtensibilitaSunday 13 May 2012 21- komponenty na sobe nezavisi primo, vetsi volnost pro obe strany kontraktu, nezavislezmeny- komponenta v ruznem kontextu, testovani v izolaci- dvě možné impementace
  22. 22. IoC kontejnerSunday 13 May 2012 22
  23. 23. • Neinvazivnost • Typy DI • Metadata • Reference mezi komponentami • Řízení vzniku komponent • Životní cyklus komponent • Jednoduchá testovatelnostSunday 13 May 2012 23základní charakteristika Spring IoC kontejneru
  24. 24. Programy před zavedením IoCSunday 13 May 2012 24
  25. 25. Programy po zavedení IoCSunday 13 May 2012 25
  26. 26. Neinvazivnost • Bean == managovaný objekt • POJO • žádný marker interface • final třídy • param. konstruktorySunday 13 May 2012 26
  27. 27. 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íSunday 13 May 2012 27Pro ruzné situace se hodi různé typy DI
  28. 28. 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óduSunday 13 May 2012 28- v aplikace obvykle zastoupeny oba dvatypy
  29. 29. Reference mezi komponentami • Typem • Bezpečnější (teoreticky) • Symbolickým jménem • Více instancí stejného typu • Variabilnější skládáníSunday 13 May 2012 29
  30. 30. Řízení vzniku komponent • Uvnitř kontextu • Delegace • Factory, Factory method • Mimo kontext • Deserializace komponenty • Web či ORM frameworkSunday 13 May 2012 30Legacy kod, 3rd party knihovny
  31. 31. XMLSunday 13 May 2012 31
  32. 32. Definice beany <bean id="" class=""></bean> • Jméno • atribut id • Typ • atribut classSunday 13 May 2012 32- jeden typ Nkrát- jméno automaticky generovane- id hlidane parserem
  33. 33. Reference(závislosti) <bean id="" class=""> <property name="" ref=""/> <property name="" value="" /> <constructor-arg ref="" value=""></constructor-arg> </bean> • Elm. property/constructor-arg • Hodnota (value) • Reference (name)Sunday 13 May 2012 33- v pripade value -Property Editor- property/constructor-arg mozno kombinovat dohromady- ridi kontejner
  34. 34. 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>Sunday 13 May 2012 34- array, set
  35. 35. 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 beansSunday 13 May 2012 35
  36. 36. Sunday 13 May 2012 36
  37. 37. Méně ukecané XML xmlns:p="http://www.springframework.org/schema/p" <bean id="myBean" class="cz.sweb.MyBean" p:dependencyA-ref="dependencyA"/>Sunday 13 May 2012 37
  38. 38. 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 samaSunday 13 May 2012 38
  39. 39. Factory <bean id="factory" class="Factory" /> <bean id="beanB" factory-bean="factory" factory-method="newInstance" /> public class Factory { public MyBeanB newInstance() { return new MyBeanB(); } }Sunday 13 May 2012 39
  40. 40. Factory method <bean id="myBeanA" class="MyBeanA" factory-method="newInstance"/> public class MyBeanA { public static MyBeanA newInstance() { return new MyBeanA(); } }Sunday 13 May 2012 40- factory method musi byt staticka
  41. 41. Init, Destroy, Lazy atd. <bean class="Bean" init-method="myInit" destroy-method="myDestroy"> <property name="depedencies" value="foo" /> </bean> import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class Bean implements InitializingBean, DisposableBean{ public Bean() {} 1 public void setDepedencies(String foo) {} 2 public void afterPropertiesSet() throws Exception {} 3 public void myInit() {} 4 public void destroy() throws Exception {} 5 public void myDestroy(){} 6 }Sunday 13 May 2012 41- rozdilny lifecycle pro singleton a prototype
  42. 42. 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 beanySunday 13 May 2012 42ukecanost - DI, transaction demarcation
  43. 43. Praktické cvičeníSunday 13 May 2012 43
  44. 44. 1.) Implementaci ReservationService a FileSystemBookStoreDao zaveďte jako beany v XML. 2.) ReservationService dostane BookStoreDao implementaci (FileSystemBookStoreDao) skrze konstruktor 3.) FileSystemBookStoreDao dostane cestu pro čtení a ukládání knih settrem 4.) 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é knihy 6.) MemoryBookStoreDao bude mít metodu destroy, která vyčistí mapu 7.) Zaveďte jednu knihu jako inner beanu do java.util.Map<Long, Book>, ktera se pouzije pro konfiguraci beany MemoryBookStoreDao 8.) Do tridy Book pridejte factory metodou newBook() 9.) Upravte definici inner beany Book, aby se vytvarela factory metodou 10.) 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.Sunday 13 May 2012 44- pokracovat v sandboxu, odkomentovat dependence
  45. 45. Jak otestovat 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() { } }Sunday 13 May 2012 45
  46. 46. AnotaceSunday 13 May 2012 46
  47. 47. Definice beany • Základní anotace na třídě • @Component • @Controller • @Service • @Repository • nepovinný atribut value (id)Sunday 13 May 2012 47- component (genericka), controller (web), service (business logika), repository (DAO)- Repository, automaticky preklad vyjimek pokud pracujeme primo JDBC, Session atd.
  48. 48. Reference(závislosti) • Základní anotace • @Autowired • field, metoda, konstruktor • @Qualifier • jemný výběr např. jménemSunday 13 May 2012 48- 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 bytpouzita namisto ni
  49. 49. @Component public 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) { } }Sunday 13 May 2012 49
  50. 50. Component scanning <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> • Stále potřebujeme XML • Aktivace anotací • Kde hledat anotované třídySunday 13 May 2012 50
  51. 51. Autowiring • Skládání objektů podle jejich závislostí • @Autowired • Řízený typem (volitelně jménem)Sunday 13 May 2012 51- autowiring funguje rovnez v XML
  52. 52. Co je potřeba vzít v potazSunday 13 May 2012 52- autowiring funguje typem by default
  53. 53. Předcházíme problémům • Buďte defenzivní • @Autowired + @Qualifier • Použití specifičtějšího typuSunday 13 May 2012 53- pouziti specifickeho typu muze selhat ve chvili proxy modu napr. anotace
  54. 54. JSR 250 & JSR 330 • JSR 250 • @Resource , @PostConstruct, @PreDestroy • JSR 330 • @Inject...Sunday 13 May 2012 54JSR 250 - jediny zpusob jak definovat init metodu anotacemi
  55. 55. Poznámka na konto anotací • + Méně ukecané • Definici beany • Závislosti • Transakce • - pouze jedna instance od každé třídy • - magické díky autowiringuSunday 13 May 2012 55
  56. 56. Praktické cvičeníSunday 13 May 2012 56
  57. 57. 1.) Beany ReservationService a MemoryBookStoreDao zavedte pomoci anotaci 2.) Pouijte anotace pro volani init a destroy metody na MemoryBookStoreDao 3.) 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.Sunday 13 May 2012 57
  58. 58. Pokročilá témataSunday 13 May 2012 58neznamená méně důležitá
  59. 59. Životní cyklus komponent • Jedna instance komponenty • Nová instance komponenty • Konverzační instance komponentySunday 13 May 2012 59
  60. 60. SingletonSunday 13 May 2012 60
  61. 61. PrototypeSunday 13 May 2012 61
  62. 62. Request, Session Proxy SingletonSunday 13 May 2012 62- zmena scope je vzdy problem (singleton vs. scope)- http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-method-injection
  63. 63. Definice • XML • atribut scope • Anotace • @Scope(value="...")Sunday 13 May 2012 63
  64. 64. Praktické cvičeníSunday 13 May 2012 64
  65. 65. 1.) Upravte definici beany Book, aby mela scope prototype 2.) Upravte definici beany java.util.Map<Long, Book>, aby pod dvema ruznymi klici referencovala beanu Book 3.) Pripravte test, ktery overi, ze List skutecne obsahuje ruzne instance beany Book 4.) Zmente scope prototype na singleton 5.) Overte testem, ze List obsahuje jednu a tu samou instanci objektu BookSunday 13 May 2012 65
  66. 66. Java ConfigSunday 13 May 2012 66
  67. 67. Java Based Config • Mix anotací a Java kódu • Alternativa k XML • @Configuration • @Bean • name, init, destroy, autowire • @ImportSunday 13 May 2012 67- lze kombinovat XML, Anotace i Java Based config- vhodné pro případy kdy v XML máme pouze deployment specifické beany a zbytek chcememít v kódu- k init, destroy lze používat jako alternativu JSR-250 anotace
  68. 68. <beans ...> <bean class="cz.sweb.pichlik.springioc.javaconfig.ConfigClass" /> zavedení configu <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"/> @Configuration <property name="username" value="${jdbc.username}"/> public class ConfigClass { <property name="password" value="${jdbc.password}"/> </bean> </beans> @Autowired private DataSource dataSource; definice beany @Bean() public MyService configureMyservice(){ return new MyService(configureJdbcDao()); } dependency injection public class MyService { @Bean() public JdbcDao configureJdbcDao() { private final DaoInterface daoInterface; return new JdbcDao(dataSource); } public MyService(DaoInterface daoInterface) { super(); @Bean() this.daoInterface = daoInterface; public HibernateDao configureHiberDao() { } return new HibernateDao(dataSource); } } }Sunday 13 May 2012 68autowiring funguje viz DataSource beana
  69. 69. Jak to funguje @Configuration • JavaConfig třídy jsou public class ConfigClass { dynamicky rozšířeny @Autowired private DataSource dataSource; • CGLIB @Bean() public MyService configureMyservice(){ return new MyService(configureJdbcDao()); } • volání @Bean() configureJdbcDao jde public JdbcDao configureJdbcDao() { přes proxy IoC kontejneru return new JdbcDao(dataSource); } @Bean() • scopes public HibernateDao configureHiberDao() { return new HibernateDao(dataSource); } } • postprocessing • autowiringSunday 13 May 2012 69
  70. 70. 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)Sunday 13 May 2012 70
  71. 71. Praktické cvičeníSunday 13 May 2012 71
  72. 72. 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 MemoryBookStoreDao 3.) 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.Sunday 13 May 2012 72

×