SlideShare una empresa de Scribd logo
1 de 72
Descargar para leer sin conexión
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
IoC container
                                        Základy




Sunday 13 May 2012                                2

Proč vzniknul Spring
Spring koncepce a organizace
Co spring nabízí a k čemu jej můžete použít
Agenda
                     • IoC obecně
                     • Chrakteristika
                     • XML
                     • Anotace
                     • Pokročilé techniky
                     • Čeho se vyvarovat
Sunday 13 May 2012                          3
Cvičení




Sunday 13 May 2012             4
• 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


Sunday 13 May 2012                                                            5

- predpripraveny projekt sandbox
- implementace BookService, knihy mohou byt v souboru viz trida Helper
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
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
Generalizace problému

                     • Kde najít

                     • Jak získat

                     • Jak zkonfigurovat

                     • Jak spojit
                       dohromady



Sunday 13 May 2012                            8

- komponenty
Inversion of Control




Sunday 13 May 2012                          9
Sunday 13 May 2012                                                          10

Martin Fowler - Continuous Integration, Refactoring, Inversion of Control
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
Dependency injection




Sunday 13 May 2012                                                      12

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




Sunday 13 May 2012                                  13

- komponenty si explicitne zadaji service locator
Service Locator vs. DI
                     • Preferujte DI
                      • Žádné těsné vazby
                      • Transparentní
                      • No singleton hell
                     • Service locator
                      • body napojení
                      • Servlet/Controller aplikace
Sunday 13 May 2012                                    14
Zrefaktorujme Váš kód




Sunday 13 May 2012                           15
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
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
Sunday 13 May 2012   18
Kontejner




Sunday 13 May 2012               19
Test




Sunday 13 May 2012          20
Benefity


                     • Indirekce == volné vazby
                      • Znovupoužitelnost
                      • Lepší testovatelnost
                      • Extensibilita


Sunday 13 May 2012                                                                       21

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




Sunday 13 May 2012                   22
• Neinvazivnost

                     • Typy DI

                     • Metadata

                     • Reference mezi komponentami

                     • Řízení vzniku komponent

                     • Životní cyklus komponent

                     • Jednoduchá testovatelnost



Sunday 13 May 2012                                   23

základní charakteristika Spring IoC kontejneru
Programy před zavedením IoC




Sunday 13 May 2012                24
Programy po zavedení IoC




Sunday 13 May 2012                      25
Neinvazivnost

                     • Bean == managovaný objekt
                      • POJO
                       • žádný marker interface
                       • final třídy
                       • param. konstruktory


Sunday 13 May 2012                                 26
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                                                  27

Pro ruzné situace se hodi různé typy DI
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ódu
Sunday 13 May 2012                                          28

- v aplikace obvykle zastoupeny oba dva
typy
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
Řízení vzniku komponent
                     • Uvnitř kontextu
                      • Delegace
                        • Factory, Factory method
                     • Mimo kontext
                      • Deserializace komponenty
                      • Web či ORM framework

Sunday 13 May 2012                                  30

Legacy kod, 3rd party knihovny
XML




Sunday 13 May 2012         31
Definice beany

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

                     • Jméno
                      • atribut id
                     • Typ
                      • atribut class

Sunday 13 May 2012                           32

- jeden typ Nkrát
- jméno automaticky generovane
- id hlidane parserem
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
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
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

Sunday 13 May 2012                                                    35
Sunday 13 May 2012   36
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
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

Sunday 13 May 2012                                        38
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
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
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
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 beany
Sunday 13 May 2012                                           42

ukecanost - DI, transaction demarcation
Praktické cvičení




Sunday 13 May 2012                       43
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
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
Anotace




Sunday 13 May 2012             46
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.
Reference(závislosti)

                     • Základní anotace
                      • @Autowired
                        • field, metoda, konstruktor
                        • @Qualifier
                         • jemný výběr např. jménem


Sunday 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 byt
pouzita namisto ni
@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
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řídy

Sunday 13 May 2012                                                                    50
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
Co je potřeba vzít v potaz




Sunday 13 May 2012                          52

- autowiring funguje typem by default
Předcházíme problémům

                     • Buďte defenzivní
                      • @Autowired + @Qualifier
                      • Použití specifičtějšího typu




Sunday 13 May 2012                                                          53

- pouziti specifickeho typu muze selhat ve chvili proxy modu napr. anotace
JSR 250 & JSR 330

                     • JSR 250
                      • @Resource , @PostConstruct,
                        @PreDestroy
                     • JSR 330
                      • @Inject...


Sunday 13 May 2012                                           54

JSR 250 - jediny zpusob jak definovat init metodu anotacemi
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

Sunday 13 May 2012                                       55
Praktické cvičení




Sunday 13 May 2012                       56
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
Pokročilá témata




Sunday 13 May 2012                      58

neznamená méně důležitá
Životní cyklus komponent


                     • Jedna instance komponenty
                     • Nová instance komponenty
                     • Konverzační instance komponenty



Sunday 13 May 2012                                       59
Singleton




Sunday 13 May 2012               60
Prototype




Sunday 13 May 2012               61
Request, Session



                                                     Proxy              Singleton




Sunday 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
Definice


                     • XML
                      • atribut scope
                     • Anotace
                      • @Scope(value="...")


Sunday 13 May 2012                            63
Praktické cvičení




Sunday 13 May 2012                       64
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 Book




Sunday 13 May 2012                                                                       65
Java Config




Sunday 13 May 2012                66
Java Based Config
                     • Mix anotací a Java kódu
                      • Alternativa k XML
                     • @Configuration
                     • @Bean
                      • name, init, destroy, autowire
                     • @Import

Sunday 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 chceme
mít v kódu
- k init, destroy lze používat jako alternativu JSR-250 anotace
<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                                                                                                                  68

autowiring funguje viz DataSource beana
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

                       • autowiring


Sunday 13 May 2012                                                                                     69
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
Praktické cvičení




Sunday 13 May 2012                       71
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

Más contenido relacionado

Más de Roman Pichlík

MongoDB for Java Developers
MongoDB for Java DevelopersMongoDB for Java Developers
MongoDB for Java DevelopersRoman Pichlík
 
Nosql from java developer pov
Nosql from java developer povNosql from java developer pov
Nosql from java developer povRoman Pichlík
 
Spring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou TvariSpring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou TvariRoman Pichlík
 
Dependency Injection Frameworky
Dependency Injection FrameworkyDependency Injection Frameworky
Dependency Injection FrameworkyRoman Pichlík
 

Más de Roman Pichlík (8)

Spring J2EE
Spring J2EESpring J2EE
Spring J2EE
 
Spring ioc-advanced
Spring ioc-advancedSpring ioc-advanced
Spring ioc-advanced
 
Spring integration
Spring integrationSpring integration
Spring integration
 
Spring Web Services
Spring Web ServicesSpring Web Services
Spring Web Services
 
MongoDB for Java Developers
MongoDB for Java DevelopersMongoDB for Java Developers
MongoDB for Java Developers
 
Nosql from java developer pov
Nosql from java developer povNosql from java developer pov
Nosql from java developer pov
 
Spring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou TvariSpring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou Tvari
 
Dependency Injection Frameworky
Dependency Injection FrameworkyDependency Injection Frameworky
Dependency Injection Frameworky
 

Spring ioc

  • 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. IoC container Základy Sunday 13 May 2012 2 Proč vzniknul Spring Spring koncepce a organizace Co spring nabízí a k čemu jej můžete použít
  • 3. Agenda • IoC obecně • Chrakteristika • XML • Anotace • Pokročilé techniky • Čeho se vyvarovat Sunday 13 May 2012 3
  • 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 ReservationServiceTest Sunday 13 May 2012 5 - predpripraveny projekt sandbox - implementace BookService, knihy mohou byt v souboru viz trida Helper
  • 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. 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. Generalizace problému • Kde najít • Jak získat • Jak zkonfigurovat • Jak spojit dohromady Sunday 13 May 2012 8 - komponenty
  • 10. Sunday 13 May 2012 10 Martin Fowler - Continuous Integration, Refactoring, Inversion of Control
  • 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. Dependency injection Sunday 13 May 2012 12 - komponenty nevi (nemusi pokud nechteji) o tom, ze je nekdo managuje - HOLLYWOOD princip
  • 13. Service locator Sunday 13 May 2012 13 - komponenty si explicitne zadaji service locator
  • 14. Service Locator vs. DI • Preferujte DI • Žádné těsné vazby • Transparentní • No singleton hell • Service locator • body napojení • Servlet/Controller aplikace Sunday 13 May 2012 14
  • 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. 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. Sunday 13 May 2012 18
  • 21. Benefity • Indirekce == volné vazby • Znovupoužitelnost • Lepší testovatelnost • Extensibilita Sunday 13 May 2012 21 - komponenty na sobe nezavisi primo, vetsi volnost pro obe strany kontraktu, nezavisle zmeny - komponenta v ruznem kontextu, testovani v izolaci - dvě možné impementace
  • 22. IoC kontejner Sunday 13 May 2012 22
  • 23. • Neinvazivnost • Typy DI • Metadata • Reference mezi komponentami • Řízení vzniku komponent • Životní cyklus komponent • Jednoduchá testovatelnost Sunday 13 May 2012 23 základní charakteristika Spring IoC kontejneru
  • 24. Programy před zavedením IoC Sunday 13 May 2012 24
  • 25. Programy po zavedení IoC Sunday 13 May 2012 25
  • 26. Neinvazivnost • Bean == managovaný objekt • POJO • žádný marker interface • final třídy • param. konstruktory Sunday 13 May 2012 26
  • 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 27 Pro ruzné situace se hodi různé typy DI
  • 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ódu Sunday 13 May 2012 28 - v aplikace obvykle zastoupeny oba dva typy
  • 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. Řízení vzniku komponent • Uvnitř kontextu • Delegace • Factory, Factory method • Mimo kontext • Deserializace komponenty • Web či ORM framework Sunday 13 May 2012 30 Legacy kod, 3rd party knihovny
  • 31. XML Sunday 13 May 2012 31
  • 32. Definice beany <bean id="" class=""></bean> • Jméno • atribut id • Typ • atribut class Sunday 13 May 2012 32 - jeden typ Nkrát - jméno automaticky generovane - id hlidane parserem
  • 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. 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. 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 Sunday 13 May 2012 35
  • 36. Sunday 13 May 2012 36
  • 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. 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 Sunday 13 May 2012 38
  • 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. 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. 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. 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 beany Sunday 13 May 2012 42 ukecanost - DI, transaction demarcation
  • 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. 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
  • 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. Reference(závislosti) • Základní anotace • @Autowired • field, metoda, konstruktor • @Qualifier • jemný výběr např. jménem Sunday 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 byt pouzita namisto ni
  • 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. 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řídy Sunday 13 May 2012 50
  • 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. Co je potřeba vzít v potaz Sunday 13 May 2012 52 - autowiring funguje typem by default
  • 53. Předcházíme problémům • Buďte defenzivní • @Autowired + @Qualifier • Použití specifičtějšího typu Sunday 13 May 2012 53 - pouziti specifickeho typu muze selhat ve chvili proxy modu napr. anotace
  • 54. JSR 250 & JSR 330 • JSR 250 • @Resource , @PostConstruct, @PreDestroy • JSR 330 • @Inject... Sunday 13 May 2012 54 JSR 250 - jediny zpusob jak definovat init metodu anotacemi
  • 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 autowiringu Sunday 13 May 2012 55
  • 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. Pokročilá témata Sunday 13 May 2012 58 neznamená méně důležitá
  • 59. Životní cyklus komponent • Jedna instance komponenty • Nová instance komponenty • Konverzační instance komponenty Sunday 13 May 2012 59
  • 62. Request, Session Proxy Singleton Sunday 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. Definice • XML • atribut scope • Anotace • @Scope(value="...") Sunday 13 May 2012 63
  • 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 Book Sunday 13 May 2012 65
  • 66. Java Config Sunday 13 May 2012 66
  • 67. Java Based Config • Mix anotací a Java kódu • Alternativa k XML • @Configuration • @Bean • name, init, destroy, autowire • @Import Sunday 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 chceme mít v kódu - k init, destroy lze používat jako alternativu JSR-250 anotace
  • 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 68 autowiring funguje viz DataSource beana
  • 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 • autowiring Sunday 13 May 2012 69
  • 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
  • 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