SlideShare una empresa de Scribd logo
1 de 59
Descargar para leer sin conexión
Spring Framework
Jens Rühmkorf
Tech Talk, DLR Köln-Porz, 17. März 2009
Inhalt


  Überblick und Einführung
  Grundlegende Prinzipien
  Funktionsweise eines DI-Frameworks am Beispiel
  Beans & ihre Konfiguration in Spring




                                                                                        Folie 2
                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Überblick und Einführung
Spring Framework
Geschichte
  Begonnen 2002/2003 von Rod Johnson und Jürgen Höller
  Spring 1.0: März 2004
  Spring 1.2.6: Jolt Productivity Award 2006 (Dr. Dobb‘s Journal)
  Spring 2.5: November 2007, aktuell 2.5.6


                                     Grundlagen und Prinzipien
                                     erschienen in Rod Johnsons
                                     Buch „Expert One-on-One J2EE
                                     Design and Development“
                                     Auslöser für die Entwicklung:
                                     Hohe Komplexität von Enterprise
                                     JavaBeans (EJB bis v2.0)



                                                                                               Folie 4
                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Spring Framework
Anforderungen an die Systemumgebung
  Spring 2.5 läuft auf JavaSE 6 und JavaEE 5
  Für bestimmte Konfigurationsmechanismen JavaSE 5 nötig
  (alles alternativ auch ohne JavaSE 5 konfigurierbar)
  Abwärtskompatibel zu Java 1.4 bzw. Java EE 1.3
  Spring-IDE 2.1 unterstützt Eclipse 3.4 (Ganymede)




                                                                                          Folie 5
                                                     Spring Framework > J. Rühmkorf > 17. März 2009
Übersicht des Spring Frameworks
http://static.springframework.org/spring/docs/2.5.x/reference/




                                                                                       Folie 6
                                                  Spring Framework > J. Rühmkorf > 17. März 2009
Spring Hello (1)              class HelloWorld


Hello World!                    -
                                        HelloW orld

                                    message: String
                                                                                      Main

                                                                           +    main(String[]) : void

                                +   hello() : void
public class HelloWorld {       +   setMessage(String) : void


  private String message;

    public void setMessage(String message) {
      this.message = message;
    }
    public void hello() {
      System.out.println("Hello! " + message);
    }
}




                                                                                                     Folie 7
                                                                Spring Framework > J. Rühmkorf > 17. März 2009
Spring Hello (2)
Main
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.
   ClassPathXmlApplicationContext;

public class Main {
  public static void main(String[] args) {
    ApplicationContext context =
      new ClassPathXmlApplicationContext("beans.xml");

        HelloWorld helloWorld =
          (HelloWorld) context.getBean("helloWorld");
        helloWorld.hello();
    }
}


                                                                                     Folie 8
                                                Spring Framework > J. Rühmkorf > 17. März 2009
Spring Hello (3)
The Glue
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="[...]" xmlns:schemaLocation="[...]">

  <bean id="helloWorld"
     class="de.dlr.spring101.hello.HelloWorld">
    <property name="message" value="TechTalk Time!"/>
  </bean>
</beans>




                                                                                 Folie 9
                                            Spring Framework > J. Rühmkorf > 17. März 2009
Spring Hello (4)
Ausgabe
17.03.2009 15:06:45 org.springframework.context.support.AbstractApplicationContext
    prepareRefresh
INFO: Refreshing
    org.springframework.context.support.ClassPathXmlApplicationContext@ab50cd:
    display name
    [org.springframework.context.support.ClassPathXmlApplicationContext@ab50cd];
    startup date [Tue Mar 17 15:06:45 CET 2009]; root of context hierarchy
17.03.2009 15:06:45 org.springframework.beans.factory.xml.XmlBeanDefinitionReader
    loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
17.03.2009 15:06:46 org.springframework.context.support.AbstractApplicationContext
    obtainFreshBeanFactory
INFO: Bean factory for application context
    [org.springframework.context.support.ClassPathXmlApplicationContext@ab50cd]:
    org.springframework.beans.factory.support.DefaultListableBeanFactory@2ce908
17.03.2009 15:06:46
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    preInstantiateSingletons
INFO: Pre-instantiating singletons in
    org.springframework.beans.factory.support.DefaultListableBeanFactory@2ce908:
    defining beans [helloWorld]; root of factory hierarchy
Hello! TechTalk Time!




                                                                                                      Folie 10
                                                                  Spring Framework > J. Rühmkorf > 17. März 2009
Grundlegende Prinzipien
„Separation of Concerns“
      (Dijkstra, 1974)
Inversion of Control (1)
Don‘t call us, we‘ll call you!
   Hollywood-Prinzip:
   „Don‘t call us, we‘ll call you!“
                                      (R.E. Sweet, SIGPLAN Notices, 1985)

   IoC-Ansatz ist typisch für Frameworks:
        „Frameworks […] emphasize design reuse over code reuse […
        leading to] an inversion of control between the application and the
        software on which it‘s based.“
        „When you use a toolkit […] you call the […] code you want to
        reuse.“
        „When you use a framework, you […] write the code it calls.“
                                     (Gang of Four, Design Patterns, 1994)




                                                                                               Folie 13
                                                           Spring Framework > J. Rühmkorf > 17. März 2009
Inversion of Control (2)
Verwendung in Frameworks
  Anwendungsentwickler:
      implementiert Callback-Methoden
      definiert was zu tun ist

  Framework:
      übernimmt die Verantwortung
      steuert zeitliche Abfolge
      definiert wann etwas zu tun ist




                                                                            Folie 14
                                        Spring Framework > J. Rühmkorf > 17. März 2009
Inversion of Control (3)
Bekannte Beispiele
  Interface ActionListener in Swing
       Zu implementieren:
       Methode void actionPerformed(ActionEvent e)
       Die Java-Runtime ruft die Methode auf bei Eintreten von Event

  Interface Runnable bei Threads
       Zu implementieren:
       Methode public void run()
       Java-Runtime entscheidet, wann run() aufgerufen wird




                                                                                            Folie 15
                                                        Spring Framework > J. Rühmkorf > 17. März 2009
Inversion of Control (4)
Typische Einsatzgebiete
  Benutzeroberflächen
  Netzwerkdienste
  Systemdienste, die System- bzw. Hardwareereignisse überwachen




                                                                                        Folie 16
                                                    Spring Framework > J. Rühmkorf > 17. März 2009
Inversion of Control (5)
Konzeptuelle Unterscheidung
  Dependency Lookup (aktiv)
      Komponente akquiriert aktiv Referenz
      „Dependency“ wird durch Lookup-Mechanismus nachgeschlagen
  Dependency Injection (passiv)
      Komponente stellt Methoden zur Injektion bereit
      Der IoC-Container injiziert die „Dependency“ buchstäblich
      kurz: DI

  Bemerkung
      Fowler benutzt DI synonym zu IoC
      http://www.martinfowler.com/articles/injection.html
      Hier wird DI als Spezialfall von IoC aufgefasst, vgl.
      http://www.picocontainer.org/inversion-of-control-history.html



                                                                                              Folie 17
                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Inversion of Control (5)
Elementare Begrifflichkeiten
  Komponente = Objekt bzw. Teil einer Software,
  dessen Ressourcen verwaltet wird von einem:
  Container = Teil einer Software,
  der Komponenten überwacht




                                                                                      Folie 18
                                                  Spring Framework > J. Rühmkorf > 17. März 2009
Dependency Lookup (1)
Dependency Pull
  Bekannteste Form von IoC
  Lese Abhängigkeiten von einer (zentralen) Registry




                                                                                           Folie 19
                                                       Spring Framework > J. Rühmkorf > 17. März 2009
Dependency Lookup (2)
   Dependency Pull am Beispiel von OSGi
    public void start(BundleContext context) {
                                                  zur Kommunikation mit
         this.context = context;
                                                  zentraler „Service
    }                                             Registry“
    public String getCustomerName(long id) {
         ServiceReference ref = context.getServiceReference(
                                ILookupService.class.getName());
         if(ref != null) {
             ILookupService lookup = (ILookupService)           schlage
                 context.getService(ref);                       Service nach
             if(lookup != null) {
                 Customer customer = lookup.findById(id);
verwende         context.ungetService(ref);
Service
                 return customer.getName();
             }
         }
         return null;
    }


                                                                                                Folie 20
                                                            Spring Framework > J. Rühmkorf > 17. März 2009
Dependency Lookup (3)
Contextualized Dependency Lookup (CDL)
    Keine zentrale Registry
    Lookup geschieht mittels eines Containers
    Container „enthält“ die Ressource / Abhängigkeit
    Jede interessierte Komponente implementiert ein Interface


public interface ManagedComponent {
     public void performLookup(Container container);
}




                                                                                              Folie 21
                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Dependency Lookup (4)
Contextualized Dependency Lookup (CDL)
  Abhängigkeit ändert sich im Container
  Container ruft component.performLookup(this) auf
  Komponente liest und verarbeitet Abhängigkeit selbst

public class ContextualizedDependencyLookup implements
   ManagedComponent {
                                      Aufruf durch
    private Dependency dep;           Container
    public void performLookup(Container container) {
        this.dep = (Dependency)
           container.getDependency("myDependency");
    }
}



                                                                                             Folie 22
                                                         Spring Framework > J. Rühmkorf > 17. März 2009
Dependency Lookup (5)
CDL = Interface Injection = Type 1 IoC
  Alternative Bezeichungen für CDL
        Interface Injection
        Type 1 IoC

  CDL hat Nachteile
         Jede Komponente muss ein Interface implementieren
         Das Interface wird vom Container festgelegt
         Verwendung der Komponente in anderem Kontext nicht möglich
  Diese Art der Injizierung wird „intrusive“ genannt
  (intrusive meint hier eindringend, stark eingreifend)




                                                                                          Folie 23
                                                      Spring Framework > J. Rühmkorf > 17. März 2009
Dependency Injection (1)
Setter Injection (= Type 2 IoC)
    Abhängigkeiten werden über Setter injiziert
    Komponente definiert set-Methoden mit Abhängigkeiten als Parameter


public class SetterInjection {
    private Dependency dep;

     public void setMyDependency(Dependency dep) {
         this.dep = dep;
     }
}




                                                                                            Folie 24
                                                        Spring Framework > J. Rühmkorf > 17. März 2009
Dependency Injection (2)
Constructor Injection (= Type 3 IoC)
    Abhängigkeiten werden über Konstruktor injiziert
    Komponente definiert Konstruktor(en) mit Abhängigkeiten als Parameter


public class ConstructorInjection {
    private Dependency dep;

     public ConstructorInjection(Dependency dep) {
         this.dep = dep;
     }
}




                                                                                             Folie 25
                                                         Spring Framework > J. Rühmkorf > 17. März 2009
Funktionsweise eines DI-Frameworks am Beispiel
Arbeitsweise des Frameworks
Beispiel: ein Reportgenerator
  Aufgabe: erzeuge Reports in HTML oder PDF
  Separiere Schnittstelle und Implementierung über ein Interface
  Dienst wird über einen ReportService bereitgestellt

     class Übersicht

                                            «interface»                                                              ReportServ ice
                                          ReportGenerator
                                  +      generate(String[][]) : void                                 +   generateAnnualReport(int) : void
                                                                                                     +   generateDailyReport(int, int, int) : void
                                                                                                     +   generateMonthlyReport(int, int) : void




           HtmlReportGenerator                                         PdfReportGenerator

       +   generate(String[][]) : void                           +     generate(String[][]) : void




                                                                                                                                                                              Folie 27
                                                                                                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (1)
Problem: Abhängig von Implementierung
    Problem: Klasse ReportService besitzt interne Abhängigkeit auf
    Implementierungsklassen (HTML, PDF)

public class ReportService {
    private ReportGenerator reportGenerator = new
        PdfReportGenerator();

     public void generateAnnualReport(int year) {
         String[][] statistics = null;
         // Erzeuge Statistiken fuer das Jahr
         reportGenerator.generate(statistics);
     }
     // Rest weggelassen
}

                                                                                              Folie 28
                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (2)
Schritt 1: Führe Container ein (UML)
  Entkopplung, Schritt 1: Führe Container-Klasse ein. Diese Klasse hat
  (Quelltext-)Abhängigkeiten auf alle Komponenten, die sie überwacht
    class Introduce Container


                                                       Containe r

                                        +   getComponent(String) : Object




                                                   «interface»                                                      ReportServ ice
                                                 ReportGenerator
                                            +   generate(String[][]) : void                           +   generateAnnualReport(int) : void
                                                                                                      +   generateDailyReport(int, int, int) : void
                                                                                                      +   generateMonthlyReport(int, int) : void




                         HtmlReportGenerator                            PdfReportGenerator

                     +   generate(String[][]) : void                +   generate(String[][]) : void




                                                                                                                                                                           Folie 29
                                                                                                                                       Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (3)
Schritt 1: Führe Container ein (cont‘d)
public class Container {
  public static Container instance;
  private Map<String, Object> components;

    public Container() {
      components = new HashMap<String, Object>();
      instance = this;
      components.put("reportGenerator", new PdfReportGenerator());
      components.put("reportService", new ReportService());
    }
    public Object getComponent(String id) {
      return components.get(id);
    }
}


                                                                                       Folie 30
                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (4)
Schritt 2: Verwende Service-Locator Pattern (UML)
  Entkopplung, Schritt 2: Verwende Service-Locator Pattern. Liegt OSGi
  zugrunde, Bestandteil von Suns Core J2EE Pattern Catalog.
      class Serv iceLocator Pattern




                                           Containe r                                                                                   Serv iceLocator

                              +   Container()                                                                              +   getReportGenerator() : ReportGenerat or
                              +   getComponent(String) : Object




                                         «interface»                                               ReportServ ice
                                       ReportGenerator
                                  +   generate(String[][]) : void                   +     generateAnnualReport(int) : void
                                                                                    +     generateDailyReport(int, int, int) : void
                                                                                    +     generateMonthlyReport(int, int) : void




                  HtmlReportGenerator                       PdfReportGenerato r

              +   generate(String[][]) : void           +   generate(String[][]) : void




                                                                                                                                                                                           Folie 31
                                                                                                                                                       Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (5)
Schritt 2: Verwende Service-Locator Pattern (cont‘d)
public class ServiceLocator {
  private static Container container = Container.instance;

    public static ReportGenerator getReportGenerator() {
      return (ReportGenerator)
        container.getComponent("reportGenerator");
    }
}

public class ReportService {
  private ReportGenerator reportGenerator =
    ServiceLocator.getReportGenerator();

    // Rest weggelassen
}

                                                                                       Folie 32
                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (6)
Schritt 3: Realisiere DI via Reflection (UML)
  Entkopplung, Schritt 3: Verwende Konfigurationsdatei um
  Abhängigkeiten von außen zu definieren.
  Instanziiere JavaBeans via Reflection.
         class DI v ia Reflection

                                                 Containe r

                                    +   Container()
                                    +   getComponent(String) : Object
                                    -   processEntry(String, String) : void




                                                «interface»                                                   ReportServ ice
                                              ReportGenerator
                                        +   generate(String[][]) : void                         +   generateAnnualReport(int) : void
                                                                                                +   generateDailyReport(int, int, int) : void
                                                                                                +   generateMonthlyReport(int, int) : void




                      HtmlReportGenerator                         PdfReportGenerator

                  +   generate(String[][]) : void             +   generate(String[][]) : void




                                                                                                                                                                                    Folie 33
                                                                                                                                                Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (7)
Schritt 3: Realisiere DI via Reflection (cont‘d)
public class Container { // Ausschnitt!
  private void processEntry(String key, String value)
    throws Exception {
    String[] parts = key.split(".");
    if (parts.length == 1) { // erzeuge Komponente
      Object component = Class.forName(value).newInstance();
      components.put(parts[0], component);
    } else { // injiziere Dependency
      Object component = components.get(parts[0]);
      Object reference = components.get(value);
      PropertyUtils.setProperty(component, parts[1], reference);
    }
  }
}


                                                                                       Folie 34
                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (8)
Schritt 3: Realisiere DI via Reflection (cont‘d)
   Konfigurationsdatei: configuration.properties
   Verwendet BeanUtils aus Apache Commons

# Definiere neue Komponente "reportGenerator"
reportGenerator=de.dlr.spring101.report.step03.
   HtmlReportGenerator

# Definiere neue Komponente "reportService"
reportService=de.dlr.spring101.report.step03.ReportService

# Injiziere die Komponente "reportGenerator"
# in das Attribut "reportGenerator"
reportService.reportGenerator=reportGenerator



                                                                                       Folie 35
                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (9)
Schritt 4: Konfiguration mit Spring Beans (UML)
  Entkopplung, Schritt 4: Verwende Spring Beans


     class DI thru Spring

                                   «interface»                                                  ReportServ ice
                                 ReportGenerator
                            +   generate(String[][]) : void                    +   generateAnnualReport(int) : void
                                                                               +   generateDailyReport(int, int, int) : void
                                                                               +   generateMonthlyReport(int, int) : void




           HtmlReportGenerator                       PdfReportGenerator

       +   generate(String[][]) : void           +   generate(String[][]) : void




                                                                                                                                                              Folie 36
                                                                                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (10)
Schritt 4: Konfiguration mit Spring Beans (cont‘d)
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.
   ClassPathXmlApplicationContext;

public class Main {
  public static void main(String[] args) {
    ApplicationContext context =
      new ClassPathXmlApplicationContext("beans.xml");
    ReportService reportService =
      (ReportService) context.getBean("reportService");
    reportService.generateAnnualReport(2008);
  }
}




                                                                                     Folie 37
                                                 Spring Framework > J. Rühmkorf > 17. März 2009
Reportgenerator (10)
Schritt 4: Konfiguration mit Spring Beans (cont‘d)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans

   http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="defaultGenerator"
     class="de.dlr.spring101.report.step04.PdfReportGenerator"/>
  <bean id="reportService"
     class="de.dlr.spring101.report.step04.ReportService">
    <property name="reportGenerator">
      <ref local="defaultGenerator"/>
    </property>
  </bean>
</beans>
                                                                                     Folie 38
                                                 Spring Framework > J. Rühmkorf > 17. März 2009
Beans & ihre Konfiguration in Spring
Begrifflichkeiten Spring und J2EE
POJO vs. JavaBean vs. (Spring) Bean
    POJO (= Plain Old Java Object). Ein POJO ist ein „simples“ Java Objekt,
    das:
      – Keine vorgegebenen Klassen erweitert,
      – keine vorgegebenen Interfaces implementiert,
      – keine vorgegebenen Annotations enthält.
–   JavaBean (J2EE Kontext): Ein JavaBean ist ein POJO das:
      – Öffentlichen Standardkonstruktor besitzt,
      – serialisierbar ist,
      – öffentliche Getter/Setter-Methoden besitzt.
–   Spring Beans:
         Komponenten heißen in Spring Beans.
         Beans == POJOs.



                                                                                              Folie 40
                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Komponenten in Spring
Spring Beans

   Bean == POJO mit eindeutiger ID
   Unterscheidung zweier Typen anhand des scope
  (= Gültigkeitsbereich)
       singleton
             Eine Instanz wird angelegt & referenziert bei jedem
            Zugriff
       prototype (nicht-singleton)
            neue Bean wird jedes Mal erzeugt
            analog zu new KlassenName()
  Weiter Typen bei Web- und Portal-Applikationen (ab Spring 2.x):
  request, session, globalSession
  Spring legt Beans i.d.R. so spät wie möglich an


                                                                                       Folie 41
                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Bean Definition (1)
Bekanntmachen von Komponenten
  Eine Bean Definition macht Spring Komponenten bekannt
  Schlüsseleigenschaften:
       class (required): Java Klassenname (fully qualified, d.h. mit
       Package)
       id: eindeutiger Bezeichner für dieses Bean
       Konfigurationsparameter (scope, init-method etc.)
       constructor-arg: An den Konstruktor zu übergebende
      Argumente
       property: An die Setter bei Erzeugung (durch Spring) zu
      übergebende Argumente
       Referenzen: andere (durch Spring verwaltete) Beans können in
      Konstruktor oder Setter-Methode referenziert werden
  Bean typischerweise in einer XML-Datei definiert


                                                                                             Folie 42
                                                         Spring Framework > J. Rühmkorf > 17. März 2009
Bean Definition (2)
Beispiel einer XML-Konfiguration
<bean id="exampleBean" class="org.example.ExampleBean">
  <property name="beanOne">
    <ref bean="anotherBean" />
  </property>
  <property name="beanTwo">
    <ref bean="yetAnotherBean" />
  </property>
  <property name="integerProperty">
    <value>1</value>
  </property>
</bean>




                                                                                Folie 43
                                            Spring Framework > J. Rühmkorf > 17. März 2009
Bean-Definition (3)
Zum Beispiel gehörige Klassendefinition
public class ExampleBean {
  private AnotherBean beanOne;
  private YetAnotherBean beanTwo;
  private int i;

    public void setBeanOne(AnotherBean beanOne) {
      this.beanOne = beanOne;
    }
    public void setBeanTwo(YetAnotherBean beanTwo) {
      this.beanTwo = beanTwo;
    }
    public void setIntegerProperty(int i) {
      this.i = i;
    }
}


                                                                                       Folie 44
                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Konfiguration des Spring IoC-Containers
BeanFactory vs. Application Context
  Konfiguration des IoC-Containers via
         XML
         Property-Dateien
         Direkter Zugriff auf die Spring-API
  BeanFactory und ApplicationContext sind zwei abstrakte
  Interfaces
  ApplicationContext erweitert BeanFactory (und weitere Interfaces)
  Ist für die meisten Anwendungsfälle zu bevorzugen




                                                                                             Folie 45
                                                         Spring Framework > J. Rühmkorf > 17. März 2009
Initialisierung des Spring IoC-Containers
Lokalisieren, Erzeugen und Verwalten von Beans
  Spring verwendet eine BeanFactory (!= FactoryBean) um Beans
  zu lokalisieren, zu erzeugen und zu verwalten
  Typischerweise verwendet man eine XML-BeanFactory:
  ApplicationContext context =
     new ClassPathXmlApplicationContext("beans.xml");




                                                                                      Folie 46
                                                  Spring Framework > J. Rühmkorf > 17. März 2009
Erzeugung von Beans (1)
Ablauf
  Ausgehend von Definitionen legt Spring Abhängigkeits-Digraphen an
  Topologische Sortierung des Graphen (falls kreisfrei) bestimmt
  Reihenfolge
       Typischerweise werden Beans erzeugt bei Laden der Definition
       Ändere dies durch Attribut lazy-init:
       <bean class="className" lazy-init="true"/>
  Graph darf Kreise enthalten, ABER:
      Initialisierungsreihenfolge dann abhängig von der Auflösung der
      Kreise, nicht mehr transparent für den Nutzer
      Auch zirkuläre Referenzen möglich, sofern die Beans per
      Constructor und nicht durch eigene Factories initialisert werden
      (sog. FactoryBean)
      Vgl. http://jira.springframework.org/browse/SPR-689



                                                                                             Folie 47
                                                         Spring Framework > J. Rühmkorf > 17. März 2009
Erzeugung von Beans (2)
Zeitpunkt der Initialisierung
   Scope singleton – werden bei Start des Containers angelegt
   Lazy via lazy-init – initialisiere erst, wenn die abhängige Bean
   angelegt wird
   „Very lazy“ – wird erst bei Zugriff auf Bean (via Container) im Quelltext
   angelegt. Dazu FactoryBean:
   LazyBean bean = (LazyBean) context.getBean("myBean");




                                                                                                Folie 48
                                                            Spring Framework > J. Rühmkorf > 17. März 2009
Injizierung von Beans
Ablauf
  Ausgangslage ist wieder der Abhängigkeitsgraph
  Beans werden durch Konstructoren oder Nutzer-spezifizierte Factory-
  Methoden erzeugt
  Abhängigkeiten, die nicht bereits durch den Konstruktor angegeben
  wurde, werden via Setter-Methoden injiziert
  Auch direktes injizieren via Annotation möglich
  (dann kein Setter oder Constructor notwendig)
  Beispiel:
  @Resource(name = "someOtherBean")
  private OtherBean otherBean;




                                                                                            Folie 49
                                                        Spring Framework > J. Rühmkorf > 17. März 2009
Setzen von Bean-Attributen
Bean Properties
  Häufigste Methode von DI: Injizierung via Properties
  Injiziert werden kann eine andere Bean, ein Wert (primitiver Datentyp,
  String), eine Collection
  <bean id="exampleBean"
     class="de.dlr.spring101.example.ExampleBean">
     <property name="anotherBean">
         <ref bean="someOtherBean" />
     </property>
  </bean>

  Kurzschreibweise:
  <bean id="exampleBean"
    class="de.dlr.spring101.example.ExampleBean">
    <property name="anotherBean" ref="someOtherBean" />
  </bean>
                                                                                              Folie 50
                                                          Spring Framework > J. Rühmkorf > 17. März 2009
JavaBean Antipattern
Überprüfen von gesetzten Attributen via Spring
  Beim Arbeiten mit JavaBeans wird ein „leeres“ Objekt initialisiert,
  das über Setter „befüllt“ wird
  Zustand ist erst valide nach Aufruf aller oder mindestens einiger Setter
  Überprüfung per Konfiguration:
  none*, simple, objects, all
  Annotation der Setter-Methoden mit @Resource:
  (einschalten via <context:annotation-config/>)
  @Required
  public void setMessage(String message) {
     this.message = message;
  }
  @Required
  public void setValue(int value) {
     this.value = value;
  }



                                                                                                      Folie 51
                                                                  Spring Framework > J. Rühmkorf > 17. März 2009
Lifecycle-Management von Beans
via Interface
   Implementiere InitializingBean oder OtherBean:
public class LifeCycle implements InitializingBean,
   DisposableBean {
  @Override
  public void afterPropertiesSet() throws Exception {
    openResource();
  }

    @Override
    public void destroy() throws Exception {
      closeResource();
    }
}


                                                                                   Folie 52
                                               Spring Framework > J. Rühmkorf > 17. März 2009
Lifecycle-Management von Beans
via Konfiguration oder Annotation
  Konfiguration:
  <bean id="lifeCycleBean"
    class="de.dlr.spring101.scratchbook.LifeCycle"
    init-method="openResource"
    destroy-method="closeResource">
    <property name="message" value="TechTalk Time!" />
  </bean>
  Annotation:
  @PreDestroy
  private void closeResource() {
    System.out.println("close resource");
  }
  @PostConstruct
  private void openResource() {
    System.out.println("open resource");
  }



                                                                                    Folie 53
                                                Spring Framework > J. Rühmkorf > 17. März 2009
Zusammenfassung & Ressourcen
Spring Core (DI)
Alternativen
  GoogleGuice: http://code.google.com/p/google-guice/
       unterstützt DI via Annotations
       viel „Autowiring“
       klein & schnell
       keine Unterstützung von Lifecycles (dazu: GuiceyFruit)
  PicoContainer: http://www.picocontainer.org/
       unterstützt DI von Typ 2+3 sowie
       unterstützt DI mittels Annotations
       Unterstützung von Lifecycles
       klein: ~260K, etabliert
  Weitere Frameworks:
       Java-Source.net
       http://java-source.net/open-source/containers


                                                                                            Folie 55
                                                        Spring Framework > J. Rühmkorf > 17. März 2009
Spring Framework
Pros and Cons
  Für Dependency Injection andere starke Frameworks verfügbar
  Spring bietet viele Module für J2EE-Kontext („Plumbing“)
  Neue Konfigurationskonzepte seit Spring 2.5:
       Annotations (Java SE 5)
       Autowiring: finde passende Komponenten „automagisch“
  Spring-Konfiguration üblicherweise sehr explizit (autowiring möglich)
  Macht das Nachvollziehen (auch für nicht-Experten) einfacher




                                                                                              Folie 56
                                                          Spring Framework > J. Rühmkorf > 17. März 2009
Literatur
Webressourcen & Artikel
[Tarr et al. 1999]
    Peri Tarr, Harold Ossher, William Harrison, and Stanley M. Sutton, Jr.
    N Degrees of Separation: Multi-dimensional Separation of Concerns
    Intl. Conf. on Software Engineering (ICSE-11, 1999)
    http://dx.doi.org/10.1145/302405.302457
[Foote, and Yoder 1997]
    Brian Foote, and Joseph Yoder
    Big Ball of Mud
    4th Conf. on Patterns Languages of Programs (PLoP ’97)
    http://www.laputan.org/mud/
[Fowler 2004]
    Martin Fowler
    Inversion of Control Containers and the Dependency Injection Pattern
    martinfowler.com, Januar 2004
    http://www.martinfowler.com/articles/injection.html
[Weiskotten 2006]
    Jeremy Weiskotten
    Dependency Injection & Testable Objects
    Dr. Dobbs Journal, April 2006
    http://www.ddj.com/185300375



                                                                                                       Folie 57
                                                                   Spring Framework > J. Rühmkorf > 17. März 2009
Literatur
Bücher zum Thema
[Gamma et al. 1994]
   Erich Gamma et al. (Gang of Four)
   Design Patterns
   Addison Wesley, November 1994
[Mak 2008]
   Gary Mak
   Spring Recipes
   Apress, Juni 2008




                                                                           Folie 58
                                       Spring Framework > J. Rühmkorf > 17. März 2009
Vielen Dank.

Más contenido relacionado

Similar a Tech Talk Spring Framework

Neue Features der Java EE 6
Neue Features der Java EE 6Neue Features der Java EE 6
Neue Features der Java EE 6GFU Cyrus AG
 
Ionic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf SteroidenIonic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf SteroidenHendrik Lösch
 
A Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragen
A Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragenA Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragen
A Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragenRoland Ewald
 
German: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptGerman: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptRalf Schwoebel
 
TYPO3 5.0 - Der aktuelle Stand der Zukunft
TYPO3 5.0 - Der aktuelle Stand der ZukunftTYPO3 5.0 - Der aktuelle Stand der Zukunft
TYPO3 5.0 - Der aktuelle Stand der ZukunftJochen Rau
 
SLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauenSLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauenSchlomo Schapiro
 
Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Joachim Baumann
 
Statische Analyse von Java-Code in der Praxis
Statische Analyse von Java-Code in der PraxisStatische Analyse von Java-Code in der Praxis
Statische Analyse von Java-Code in der PraxisRoland Ewald
 
Programmierung von Mobiltelefonen mit Python
Programmierung von Mobiltelefonen mit PythonProgrammierung von Mobiltelefonen mit Python
Programmierung von Mobiltelefonen mit PythonAndreas Schreiber
 
Top 10 Internet Trends 2001
Top 10 Internet Trends 2001Top 10 Internet Trends 2001
Top 10 Internet Trends 2001Jürg Stuker
 
Introduction to JEE
Introduction to JEEIntroduction to JEE
Introduction to JEEguestc44b7b
 
Why websecurity sucks
Why websecurity sucksWhy websecurity sucks
Why websecurity sucksThaDafinser
 
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbHEntwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbHstijink
 
OSGi und Spring MVC - inovex BrownBag
OSGi und Spring MVC - inovex BrownBag OSGi und Spring MVC - inovex BrownBag
OSGi und Spring MVC - inovex BrownBag inovex GmbH
 

Similar a Tech Talk Spring Framework (20)

Symfony2
Symfony2Symfony2
Symfony2
 
Neue Features der Java EE 6
Neue Features der Java EE 6Neue Features der Java EE 6
Neue Features der Java EE 6
 
Ionic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf SteroidenIonic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf Steroiden
 
A Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragen
A Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragenA Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragen
A Day in the Life of a Bug --- sinnvoll zu Open Source Projekten beitragen
 
German: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptGerman: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit Javascript
 
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-TestsIks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
 
TYPO3 5.0 - Der aktuelle Stand der Zukunft
TYPO3 5.0 - Der aktuelle Stand der ZukunftTYPO3 5.0 - Der aktuelle Stand der Zukunft
TYPO3 5.0 - Der aktuelle Stand der Zukunft
 
SLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauenSLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauen
 
Ionic 3
Ionic 3Ionic 3
Ionic 3
 
Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)Gradle - Beginner's Workshop (german)
Gradle - Beginner's Workshop (german)
 
Statische Analyse von Java-Code in der Praxis
Statische Analyse von Java-Code in der PraxisStatische Analyse von Java-Code in der Praxis
Statische Analyse von Java-Code in der Praxis
 
C++ kompakt
C++ kompaktC++ kompakt
C++ kompakt
 
Enterprise JS
Enterprise JS Enterprise JS
Enterprise JS
 
Programmierung von Mobiltelefonen mit Python
Programmierung von Mobiltelefonen mit PythonProgrammierung von Mobiltelefonen mit Python
Programmierung von Mobiltelefonen mit Python
 
Top 10 Internet Trends 2001
Top 10 Internet Trends 2001Top 10 Internet Trends 2001
Top 10 Internet Trends 2001
 
Maven Intro
Maven IntroMaven Intro
Maven Intro
 
Introduction to JEE
Introduction to JEEIntroduction to JEE
Introduction to JEE
 
Why websecurity sucks
Why websecurity sucksWhy websecurity sucks
Why websecurity sucks
 
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbHEntwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
Entwicklungsprozess und Arbeit mit Symfony2 in der fotocommunity GmbH
 
OSGi und Spring MVC - inovex BrownBag
OSGi und Spring MVC - inovex BrownBag OSGi und Spring MVC - inovex BrownBag
OSGi und Spring MVC - inovex BrownBag
 

Tech Talk Spring Framework

  • 1. Spring Framework Jens Rühmkorf Tech Talk, DLR Köln-Porz, 17. März 2009
  • 2. Inhalt Überblick und Einführung Grundlegende Prinzipien Funktionsweise eines DI-Frameworks am Beispiel Beans & ihre Konfiguration in Spring Folie 2 Spring Framework > J. Rühmkorf > 17. März 2009
  • 4. Spring Framework Geschichte Begonnen 2002/2003 von Rod Johnson und Jürgen Höller Spring 1.0: März 2004 Spring 1.2.6: Jolt Productivity Award 2006 (Dr. Dobb‘s Journal) Spring 2.5: November 2007, aktuell 2.5.6 Grundlagen und Prinzipien erschienen in Rod Johnsons Buch „Expert One-on-One J2EE Design and Development“ Auslöser für die Entwicklung: Hohe Komplexität von Enterprise JavaBeans (EJB bis v2.0) Folie 4 Spring Framework > J. Rühmkorf > 17. März 2009
  • 5. Spring Framework Anforderungen an die Systemumgebung Spring 2.5 läuft auf JavaSE 6 und JavaEE 5 Für bestimmte Konfigurationsmechanismen JavaSE 5 nötig (alles alternativ auch ohne JavaSE 5 konfigurierbar) Abwärtskompatibel zu Java 1.4 bzw. Java EE 1.3 Spring-IDE 2.1 unterstützt Eclipse 3.4 (Ganymede) Folie 5 Spring Framework > J. Rühmkorf > 17. März 2009
  • 6. Übersicht des Spring Frameworks http://static.springframework.org/spring/docs/2.5.x/reference/ Folie 6 Spring Framework > J. Rühmkorf > 17. März 2009
  • 7. Spring Hello (1) class HelloWorld Hello World! - HelloW orld message: String Main + main(String[]) : void + hello() : void public class HelloWorld { + setMessage(String) : void private String message; public void setMessage(String message) { this.message = message; } public void hello() { System.out.println("Hello! " + message); } } Folie 7 Spring Framework > J. Rühmkorf > 17. März 2009
  • 8. Spring Hello (2) Main import org.springframework.context.ApplicationContext; import org.springframework.context.support. ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld"); helloWorld.hello(); } } Folie 8 Spring Framework > J. Rühmkorf > 17. März 2009
  • 9. Spring Hello (3) The Glue <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="[...]" xmlns:schemaLocation="[...]"> <bean id="helloWorld" class="de.dlr.spring101.hello.HelloWorld"> <property name="message" value="TechTalk Time!"/> </bean> </beans> Folie 9 Spring Framework > J. Rühmkorf > 17. März 2009
  • 10. Spring Hello (4) Ausgabe 17.03.2009 15:06:45 org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@ab50cd: display name [org.springframework.context.support.ClassPathXmlApplicationContext@ab50cd]; startup date [Tue Mar 17 15:06:45 CET 2009]; root of context hierarchy 17.03.2009 15:06:45 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [beans.xml] 17.03.2009 15:06:46 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@ab50cd]: org.springframework.beans.factory.support.DefaultListableBeanFactory@2ce908 17.03.2009 15:06:46 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2ce908: defining beans [helloWorld]; root of factory hierarchy Hello! TechTalk Time! Folie 10 Spring Framework > J. Rühmkorf > 17. März 2009
  • 12. „Separation of Concerns“ (Dijkstra, 1974)
  • 13. Inversion of Control (1) Don‘t call us, we‘ll call you! Hollywood-Prinzip: „Don‘t call us, we‘ll call you!“ (R.E. Sweet, SIGPLAN Notices, 1985) IoC-Ansatz ist typisch für Frameworks: „Frameworks […] emphasize design reuse over code reuse [… leading to] an inversion of control between the application and the software on which it‘s based.“ „When you use a toolkit […] you call the […] code you want to reuse.“ „When you use a framework, you […] write the code it calls.“ (Gang of Four, Design Patterns, 1994) Folie 13 Spring Framework > J. Rühmkorf > 17. März 2009
  • 14. Inversion of Control (2) Verwendung in Frameworks Anwendungsentwickler: implementiert Callback-Methoden definiert was zu tun ist Framework: übernimmt die Verantwortung steuert zeitliche Abfolge definiert wann etwas zu tun ist Folie 14 Spring Framework > J. Rühmkorf > 17. März 2009
  • 15. Inversion of Control (3) Bekannte Beispiele Interface ActionListener in Swing Zu implementieren: Methode void actionPerformed(ActionEvent e) Die Java-Runtime ruft die Methode auf bei Eintreten von Event Interface Runnable bei Threads Zu implementieren: Methode public void run() Java-Runtime entscheidet, wann run() aufgerufen wird Folie 15 Spring Framework > J. Rühmkorf > 17. März 2009
  • 16. Inversion of Control (4) Typische Einsatzgebiete Benutzeroberflächen Netzwerkdienste Systemdienste, die System- bzw. Hardwareereignisse überwachen Folie 16 Spring Framework > J. Rühmkorf > 17. März 2009
  • 17. Inversion of Control (5) Konzeptuelle Unterscheidung Dependency Lookup (aktiv) Komponente akquiriert aktiv Referenz „Dependency“ wird durch Lookup-Mechanismus nachgeschlagen Dependency Injection (passiv) Komponente stellt Methoden zur Injektion bereit Der IoC-Container injiziert die „Dependency“ buchstäblich kurz: DI Bemerkung Fowler benutzt DI synonym zu IoC http://www.martinfowler.com/articles/injection.html Hier wird DI als Spezialfall von IoC aufgefasst, vgl. http://www.picocontainer.org/inversion-of-control-history.html Folie 17 Spring Framework > J. Rühmkorf > 17. März 2009
  • 18. Inversion of Control (5) Elementare Begrifflichkeiten Komponente = Objekt bzw. Teil einer Software, dessen Ressourcen verwaltet wird von einem: Container = Teil einer Software, der Komponenten überwacht Folie 18 Spring Framework > J. Rühmkorf > 17. März 2009
  • 19. Dependency Lookup (1) Dependency Pull Bekannteste Form von IoC Lese Abhängigkeiten von einer (zentralen) Registry Folie 19 Spring Framework > J. Rühmkorf > 17. März 2009
  • 20. Dependency Lookup (2) Dependency Pull am Beispiel von OSGi public void start(BundleContext context) { zur Kommunikation mit this.context = context; zentraler „Service } Registry“ public String getCustomerName(long id) { ServiceReference ref = context.getServiceReference( ILookupService.class.getName()); if(ref != null) { ILookupService lookup = (ILookupService) schlage context.getService(ref); Service nach if(lookup != null) { Customer customer = lookup.findById(id); verwende context.ungetService(ref); Service return customer.getName(); } } return null; } Folie 20 Spring Framework > J. Rühmkorf > 17. März 2009
  • 21. Dependency Lookup (3) Contextualized Dependency Lookup (CDL) Keine zentrale Registry Lookup geschieht mittels eines Containers Container „enthält“ die Ressource / Abhängigkeit Jede interessierte Komponente implementiert ein Interface public interface ManagedComponent { public void performLookup(Container container); } Folie 21 Spring Framework > J. Rühmkorf > 17. März 2009
  • 22. Dependency Lookup (4) Contextualized Dependency Lookup (CDL) Abhängigkeit ändert sich im Container Container ruft component.performLookup(this) auf Komponente liest und verarbeitet Abhängigkeit selbst public class ContextualizedDependencyLookup implements ManagedComponent { Aufruf durch private Dependency dep; Container public void performLookup(Container container) { this.dep = (Dependency) container.getDependency("myDependency"); } } Folie 22 Spring Framework > J. Rühmkorf > 17. März 2009
  • 23. Dependency Lookup (5) CDL = Interface Injection = Type 1 IoC Alternative Bezeichungen für CDL Interface Injection Type 1 IoC CDL hat Nachteile Jede Komponente muss ein Interface implementieren Das Interface wird vom Container festgelegt Verwendung der Komponente in anderem Kontext nicht möglich Diese Art der Injizierung wird „intrusive“ genannt (intrusive meint hier eindringend, stark eingreifend) Folie 23 Spring Framework > J. Rühmkorf > 17. März 2009
  • 24. Dependency Injection (1) Setter Injection (= Type 2 IoC) Abhängigkeiten werden über Setter injiziert Komponente definiert set-Methoden mit Abhängigkeiten als Parameter public class SetterInjection { private Dependency dep; public void setMyDependency(Dependency dep) { this.dep = dep; } } Folie 24 Spring Framework > J. Rühmkorf > 17. März 2009
  • 25. Dependency Injection (2) Constructor Injection (= Type 3 IoC) Abhängigkeiten werden über Konstruktor injiziert Komponente definiert Konstruktor(en) mit Abhängigkeiten als Parameter public class ConstructorInjection { private Dependency dep; public ConstructorInjection(Dependency dep) { this.dep = dep; } } Folie 25 Spring Framework > J. Rühmkorf > 17. März 2009
  • 27. Arbeitsweise des Frameworks Beispiel: ein Reportgenerator Aufgabe: erzeuge Reports in HTML oder PDF Separiere Schnittstelle und Implementierung über ein Interface Dienst wird über einen ReportService bereitgestellt class Übersicht «interface» ReportServ ice ReportGenerator + generate(String[][]) : void + generateAnnualReport(int) : void + generateDailyReport(int, int, int) : void + generateMonthlyReport(int, int) : void HtmlReportGenerator PdfReportGenerator + generate(String[][]) : void + generate(String[][]) : void Folie 27 Spring Framework > J. Rühmkorf > 17. März 2009
  • 28. Reportgenerator (1) Problem: Abhängig von Implementierung Problem: Klasse ReportService besitzt interne Abhängigkeit auf Implementierungsklassen (HTML, PDF) public class ReportService { private ReportGenerator reportGenerator = new PdfReportGenerator(); public void generateAnnualReport(int year) { String[][] statistics = null; // Erzeuge Statistiken fuer das Jahr reportGenerator.generate(statistics); } // Rest weggelassen } Folie 28 Spring Framework > J. Rühmkorf > 17. März 2009
  • 29. Reportgenerator (2) Schritt 1: Führe Container ein (UML) Entkopplung, Schritt 1: Führe Container-Klasse ein. Diese Klasse hat (Quelltext-)Abhängigkeiten auf alle Komponenten, die sie überwacht class Introduce Container Containe r + getComponent(String) : Object «interface» ReportServ ice ReportGenerator + generate(String[][]) : void + generateAnnualReport(int) : void + generateDailyReport(int, int, int) : void + generateMonthlyReport(int, int) : void HtmlReportGenerator PdfReportGenerator + generate(String[][]) : void + generate(String[][]) : void Folie 29 Spring Framework > J. Rühmkorf > 17. März 2009
  • 30. Reportgenerator (3) Schritt 1: Führe Container ein (cont‘d) public class Container { public static Container instance; private Map<String, Object> components; public Container() { components = new HashMap<String, Object>(); instance = this; components.put("reportGenerator", new PdfReportGenerator()); components.put("reportService", new ReportService()); } public Object getComponent(String id) { return components.get(id); } } Folie 30 Spring Framework > J. Rühmkorf > 17. März 2009
  • 31. Reportgenerator (4) Schritt 2: Verwende Service-Locator Pattern (UML) Entkopplung, Schritt 2: Verwende Service-Locator Pattern. Liegt OSGi zugrunde, Bestandteil von Suns Core J2EE Pattern Catalog. class Serv iceLocator Pattern Containe r Serv iceLocator + Container() + getReportGenerator() : ReportGenerat or + getComponent(String) : Object «interface» ReportServ ice ReportGenerator + generate(String[][]) : void + generateAnnualReport(int) : void + generateDailyReport(int, int, int) : void + generateMonthlyReport(int, int) : void HtmlReportGenerator PdfReportGenerato r + generate(String[][]) : void + generate(String[][]) : void Folie 31 Spring Framework > J. Rühmkorf > 17. März 2009
  • 32. Reportgenerator (5) Schritt 2: Verwende Service-Locator Pattern (cont‘d) public class ServiceLocator { private static Container container = Container.instance; public static ReportGenerator getReportGenerator() { return (ReportGenerator) container.getComponent("reportGenerator"); } } public class ReportService { private ReportGenerator reportGenerator = ServiceLocator.getReportGenerator(); // Rest weggelassen } Folie 32 Spring Framework > J. Rühmkorf > 17. März 2009
  • 33. Reportgenerator (6) Schritt 3: Realisiere DI via Reflection (UML) Entkopplung, Schritt 3: Verwende Konfigurationsdatei um Abhängigkeiten von außen zu definieren. Instanziiere JavaBeans via Reflection. class DI v ia Reflection Containe r + Container() + getComponent(String) : Object - processEntry(String, String) : void «interface» ReportServ ice ReportGenerator + generate(String[][]) : void + generateAnnualReport(int) : void + generateDailyReport(int, int, int) : void + generateMonthlyReport(int, int) : void HtmlReportGenerator PdfReportGenerator + generate(String[][]) : void + generate(String[][]) : void Folie 33 Spring Framework > J. Rühmkorf > 17. März 2009
  • 34. Reportgenerator (7) Schritt 3: Realisiere DI via Reflection (cont‘d) public class Container { // Ausschnitt! private void processEntry(String key, String value) throws Exception { String[] parts = key.split("."); if (parts.length == 1) { // erzeuge Komponente Object component = Class.forName(value).newInstance(); components.put(parts[0], component); } else { // injiziere Dependency Object component = components.get(parts[0]); Object reference = components.get(value); PropertyUtils.setProperty(component, parts[1], reference); } } } Folie 34 Spring Framework > J. Rühmkorf > 17. März 2009
  • 35. Reportgenerator (8) Schritt 3: Realisiere DI via Reflection (cont‘d) Konfigurationsdatei: configuration.properties Verwendet BeanUtils aus Apache Commons # Definiere neue Komponente "reportGenerator" reportGenerator=de.dlr.spring101.report.step03. HtmlReportGenerator # Definiere neue Komponente "reportService" reportService=de.dlr.spring101.report.step03.ReportService # Injiziere die Komponente "reportGenerator" # in das Attribut "reportGenerator" reportService.reportGenerator=reportGenerator Folie 35 Spring Framework > J. Rühmkorf > 17. März 2009
  • 36. Reportgenerator (9) Schritt 4: Konfiguration mit Spring Beans (UML) Entkopplung, Schritt 4: Verwende Spring Beans class DI thru Spring «interface» ReportServ ice ReportGenerator + generate(String[][]) : void + generateAnnualReport(int) : void + generateDailyReport(int, int, int) : void + generateMonthlyReport(int, int) : void HtmlReportGenerator PdfReportGenerator + generate(String[][]) : void + generate(String[][]) : void Folie 36 Spring Framework > J. Rühmkorf > 17. März 2009
  • 37. Reportgenerator (10) Schritt 4: Konfiguration mit Spring Beans (cont‘d) import org.springframework.context.ApplicationContext; import org.springframework.context.support. ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); ReportService reportService = (ReportService) context.getBean("reportService"); reportService.generateAnnualReport(2008); } } Folie 37 Spring Framework > J. Rühmkorf > 17. März 2009
  • 38. Reportgenerator (10) Schritt 4: Konfiguration mit Spring Beans (cont‘d) <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="defaultGenerator" class="de.dlr.spring101.report.step04.PdfReportGenerator"/> <bean id="reportService" class="de.dlr.spring101.report.step04.ReportService"> <property name="reportGenerator"> <ref local="defaultGenerator"/> </property> </bean> </beans> Folie 38 Spring Framework > J. Rühmkorf > 17. März 2009
  • 39. Beans & ihre Konfiguration in Spring
  • 40. Begrifflichkeiten Spring und J2EE POJO vs. JavaBean vs. (Spring) Bean POJO (= Plain Old Java Object). Ein POJO ist ein „simples“ Java Objekt, das: – Keine vorgegebenen Klassen erweitert, – keine vorgegebenen Interfaces implementiert, – keine vorgegebenen Annotations enthält. – JavaBean (J2EE Kontext): Ein JavaBean ist ein POJO das: – Öffentlichen Standardkonstruktor besitzt, – serialisierbar ist, – öffentliche Getter/Setter-Methoden besitzt. – Spring Beans: Komponenten heißen in Spring Beans. Beans == POJOs. Folie 40 Spring Framework > J. Rühmkorf > 17. März 2009
  • 41. Komponenten in Spring Spring Beans Bean == POJO mit eindeutiger ID Unterscheidung zweier Typen anhand des scope (= Gültigkeitsbereich) singleton Eine Instanz wird angelegt & referenziert bei jedem Zugriff prototype (nicht-singleton) neue Bean wird jedes Mal erzeugt analog zu new KlassenName() Weiter Typen bei Web- und Portal-Applikationen (ab Spring 2.x): request, session, globalSession Spring legt Beans i.d.R. so spät wie möglich an Folie 41 Spring Framework > J. Rühmkorf > 17. März 2009
  • 42. Bean Definition (1) Bekanntmachen von Komponenten Eine Bean Definition macht Spring Komponenten bekannt Schlüsseleigenschaften: class (required): Java Klassenname (fully qualified, d.h. mit Package) id: eindeutiger Bezeichner für dieses Bean Konfigurationsparameter (scope, init-method etc.) constructor-arg: An den Konstruktor zu übergebende Argumente property: An die Setter bei Erzeugung (durch Spring) zu übergebende Argumente Referenzen: andere (durch Spring verwaltete) Beans können in Konstruktor oder Setter-Methode referenziert werden Bean typischerweise in einer XML-Datei definiert Folie 42 Spring Framework > J. Rühmkorf > 17. März 2009
  • 43. Bean Definition (2) Beispiel einer XML-Konfiguration <bean id="exampleBean" class="org.example.ExampleBean"> <property name="beanOne"> <ref bean="anotherBean" /> </property> <property name="beanTwo"> <ref bean="yetAnotherBean" /> </property> <property name="integerProperty"> <value>1</value> </property> </bean> Folie 43 Spring Framework > J. Rühmkorf > 17. März 2009
  • 44. Bean-Definition (3) Zum Beispiel gehörige Klassendefinition public class ExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public void setBeanOne(AnotherBean beanOne) { this.beanOne = beanOne; } public void setBeanTwo(YetAnotherBean beanTwo) { this.beanTwo = beanTwo; } public void setIntegerProperty(int i) { this.i = i; } } Folie 44 Spring Framework > J. Rühmkorf > 17. März 2009
  • 45. Konfiguration des Spring IoC-Containers BeanFactory vs. Application Context Konfiguration des IoC-Containers via XML Property-Dateien Direkter Zugriff auf die Spring-API BeanFactory und ApplicationContext sind zwei abstrakte Interfaces ApplicationContext erweitert BeanFactory (und weitere Interfaces) Ist für die meisten Anwendungsfälle zu bevorzugen Folie 45 Spring Framework > J. Rühmkorf > 17. März 2009
  • 46. Initialisierung des Spring IoC-Containers Lokalisieren, Erzeugen und Verwalten von Beans Spring verwendet eine BeanFactory (!= FactoryBean) um Beans zu lokalisieren, zu erzeugen und zu verwalten Typischerweise verwendet man eine XML-BeanFactory: ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Folie 46 Spring Framework > J. Rühmkorf > 17. März 2009
  • 47. Erzeugung von Beans (1) Ablauf Ausgehend von Definitionen legt Spring Abhängigkeits-Digraphen an Topologische Sortierung des Graphen (falls kreisfrei) bestimmt Reihenfolge Typischerweise werden Beans erzeugt bei Laden der Definition Ändere dies durch Attribut lazy-init: <bean class="className" lazy-init="true"/> Graph darf Kreise enthalten, ABER: Initialisierungsreihenfolge dann abhängig von der Auflösung der Kreise, nicht mehr transparent für den Nutzer Auch zirkuläre Referenzen möglich, sofern die Beans per Constructor und nicht durch eigene Factories initialisert werden (sog. FactoryBean) Vgl. http://jira.springframework.org/browse/SPR-689 Folie 47 Spring Framework > J. Rühmkorf > 17. März 2009
  • 48. Erzeugung von Beans (2) Zeitpunkt der Initialisierung Scope singleton – werden bei Start des Containers angelegt Lazy via lazy-init – initialisiere erst, wenn die abhängige Bean angelegt wird „Very lazy“ – wird erst bei Zugriff auf Bean (via Container) im Quelltext angelegt. Dazu FactoryBean: LazyBean bean = (LazyBean) context.getBean("myBean"); Folie 48 Spring Framework > J. Rühmkorf > 17. März 2009
  • 49. Injizierung von Beans Ablauf Ausgangslage ist wieder der Abhängigkeitsgraph Beans werden durch Konstructoren oder Nutzer-spezifizierte Factory- Methoden erzeugt Abhängigkeiten, die nicht bereits durch den Konstruktor angegeben wurde, werden via Setter-Methoden injiziert Auch direktes injizieren via Annotation möglich (dann kein Setter oder Constructor notwendig) Beispiel: @Resource(name = "someOtherBean") private OtherBean otherBean; Folie 49 Spring Framework > J. Rühmkorf > 17. März 2009
  • 50. Setzen von Bean-Attributen Bean Properties Häufigste Methode von DI: Injizierung via Properties Injiziert werden kann eine andere Bean, ein Wert (primitiver Datentyp, String), eine Collection <bean id="exampleBean" class="de.dlr.spring101.example.ExampleBean"> <property name="anotherBean"> <ref bean="someOtherBean" /> </property> </bean> Kurzschreibweise: <bean id="exampleBean" class="de.dlr.spring101.example.ExampleBean"> <property name="anotherBean" ref="someOtherBean" /> </bean> Folie 50 Spring Framework > J. Rühmkorf > 17. März 2009
  • 51. JavaBean Antipattern Überprüfen von gesetzten Attributen via Spring Beim Arbeiten mit JavaBeans wird ein „leeres“ Objekt initialisiert, das über Setter „befüllt“ wird Zustand ist erst valide nach Aufruf aller oder mindestens einiger Setter Überprüfung per Konfiguration: none*, simple, objects, all Annotation der Setter-Methoden mit @Resource: (einschalten via <context:annotation-config/>) @Required public void setMessage(String message) { this.message = message; } @Required public void setValue(int value) { this.value = value; } Folie 51 Spring Framework > J. Rühmkorf > 17. März 2009
  • 52. Lifecycle-Management von Beans via Interface Implementiere InitializingBean oder OtherBean: public class LifeCycle implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { openResource(); } @Override public void destroy() throws Exception { closeResource(); } } Folie 52 Spring Framework > J. Rühmkorf > 17. März 2009
  • 53. Lifecycle-Management von Beans via Konfiguration oder Annotation Konfiguration: <bean id="lifeCycleBean" class="de.dlr.spring101.scratchbook.LifeCycle" init-method="openResource" destroy-method="closeResource"> <property name="message" value="TechTalk Time!" /> </bean> Annotation: @PreDestroy private void closeResource() { System.out.println("close resource"); } @PostConstruct private void openResource() { System.out.println("open resource"); } Folie 53 Spring Framework > J. Rühmkorf > 17. März 2009
  • 55. Spring Core (DI) Alternativen GoogleGuice: http://code.google.com/p/google-guice/ unterstützt DI via Annotations viel „Autowiring“ klein & schnell keine Unterstützung von Lifecycles (dazu: GuiceyFruit) PicoContainer: http://www.picocontainer.org/ unterstützt DI von Typ 2+3 sowie unterstützt DI mittels Annotations Unterstützung von Lifecycles klein: ~260K, etabliert Weitere Frameworks: Java-Source.net http://java-source.net/open-source/containers Folie 55 Spring Framework > J. Rühmkorf > 17. März 2009
  • 56. Spring Framework Pros and Cons Für Dependency Injection andere starke Frameworks verfügbar Spring bietet viele Module für J2EE-Kontext („Plumbing“) Neue Konfigurationskonzepte seit Spring 2.5: Annotations (Java SE 5) Autowiring: finde passende Komponenten „automagisch“ Spring-Konfiguration üblicherweise sehr explizit (autowiring möglich) Macht das Nachvollziehen (auch für nicht-Experten) einfacher Folie 56 Spring Framework > J. Rühmkorf > 17. März 2009
  • 57. Literatur Webressourcen & Artikel [Tarr et al. 1999] Peri Tarr, Harold Ossher, William Harrison, and Stanley M. Sutton, Jr. N Degrees of Separation: Multi-dimensional Separation of Concerns Intl. Conf. on Software Engineering (ICSE-11, 1999) http://dx.doi.org/10.1145/302405.302457 [Foote, and Yoder 1997] Brian Foote, and Joseph Yoder Big Ball of Mud 4th Conf. on Patterns Languages of Programs (PLoP ’97) http://www.laputan.org/mud/ [Fowler 2004] Martin Fowler Inversion of Control Containers and the Dependency Injection Pattern martinfowler.com, Januar 2004 http://www.martinfowler.com/articles/injection.html [Weiskotten 2006] Jeremy Weiskotten Dependency Injection & Testable Objects Dr. Dobbs Journal, April 2006 http://www.ddj.com/185300375 Folie 57 Spring Framework > J. Rühmkorf > 17. März 2009
  • 58. Literatur Bücher zum Thema [Gamma et al. 1994] Erich Gamma et al. (Gang of Four) Design Patterns Addison Wesley, November 1994 [Mak 2008] Gary Mak Spring Recipes Apress, Juni 2008 Folie 58 Spring Framework > J. Rühmkorf > 17. März 2009