0
Spring Framework Jens Rühmkorf  Tech Talk, DLR Köln-Porz, 17. März 2009
Inhalt <ul><li>Überblick und Einführung </li></ul><ul><li>Grundlegende Prinzipien </li></ul><ul><li>Funktionsweise eines D...
Überblick und Einführung
Spring Framework Geschichte <ul><li>Begonnen 2002/2003 von Rod Johnson und Jürgen Höller </li></ul><ul><li>Spring 1.0: Mär...
Spring Framework Anforderungen an die Systemumgebung <ul><li>Spring 2.5 läuft auf JavaSE 6 und JavaEE 5 </li></ul><ul><li>...
Übersicht des Spring Frameworks http://static.springframework.org/spring/docs/2.5.x/reference/
Spring Hello (1) Hello World!  <ul><li>public   class  HelloWorld { </li></ul><ul><li>private  String  message ; </li></ul...
Spring Hello (2) Main <ul><li>import  org.springframework.context.ApplicationContext; </li></ul><ul><li>import  org.spring...
Spring Hello (3) The Glue <ul><li>< beans   xmlns = &quot;http://www.springframework.org/schema/beans&quot;  xmlns:xsi = &...
Spring Hello (4) Ausgabe <ul><li>17.03.2009 15:06:45 org.springframework.context.support.AbstractApplicationContext prepar...
Grundlegende Prinzipien
„ Separation of Concerns “ (Dijkstra, 1974)
Inversion of Control (1) Don‘t call us, we‘ll call you! <ul><li>Hollywood-Prinzip:  „ Don‘t call us, we‘ll call you! “ </l...
Inversion of Control (2) Verwendung in Frameworks <ul><li>Anwendungsentwickler: </li></ul><ul><ul><li>implementiert  Callb...
Inversion of Control (3) Bekannte Beispiele <ul><li>Interface  ActionListener  in Swing </li></ul><ul><ul><li>Zu implement...
Inversion of Control (4) Typische Einsatzgebiete <ul><li>Benutzeroberflächen </li></ul><ul><li>Netzwerkdienste </li></ul><...
Inversion of Control (5) Konzeptuelle Unterscheidung <ul><li>Dependency Lookup (aktiv) </li></ul><ul><ul><li>Komponente ak...
Inversion of Control (5) Elementare Begrifflichkeiten <ul><li>Komponente  = Objekt bzw. Teil einer Software,  dessen Resso...
Dependency Lookup (1) Dependency Pull <ul><li>Bekannteste Form von IoC </li></ul><ul><li>Lese Abhängigkeiten von einer (ze...
<ul><li>public   void  start(BundleContext context) { </li></ul><ul><li>this . context  = context; </li></ul><ul><li>} </l...
Dependency Lookup (3) Contextualized Dependency Lookup (CDL) <ul><li>Keine zentrale Registry </li></ul><ul><li>Lookup gesc...
Dependency Lookup (4) Contextualized Dependency Lookup (CDL) <ul><li>Abhängigkeit ändert sich im Container  </li></ul><ul>...
Dependency Lookup (5) CDL = Interface Injection = Type 1 IoC <ul><li>Alternative Bezeichungen für CDL </li></ul><ul><ul><l...
Dependency Injection (1) Setter Injection (= Type 2 IoC) <ul><li>Abhängigkeiten werden über Setter injiziert </li></ul><ul...
Dependency Injection (2) Constructor Injection (= Type 3 IoC) <ul><li>Abhängigkeiten werden über Konstruktor injiziert </l...
Funktionsweise eines DI-Frameworks am Beispiel
Arbeitsweise des Frameworks Beispiel: ein Reportgenerator <ul><li>Aufgabe: erzeuge Reports in HTML oder PDF </li></ul><ul>...
Reportgenerator (1) Problem: Abhängig von Implementierung <ul><li>Problem:  Klasse ReportService besitzt interne Abhängigk...
Reportgenerator (2) Schritt 1: Führe Container ein (UML) <ul><li>Entkopplung, Schritt 1:  Führe Container-Klasse ein. Dies...
Reportgenerator (3) Schritt 1: Führe Container ein (cont‘d) public   class  Container { public   static  Container  instan...
Reportgenerator (4) Schritt 2: Verwende Service-Locator Pattern (UML) <ul><li>Entkopplung, Schritt 2:  Verwende Service-Lo...
Reportgenerator (5) Schritt 2: Verwende Service-Locator Pattern (cont‘d) public   class  ServiceLocator { private   static...
Reportgenerator (6) Schritt 3: Realisiere DI via Reflection (UML) <ul><li>Entkopplung, Schritt 3:  Verwende Konfigurations...
Reportgenerator (7) Schritt 3: Realisiere DI via Reflection (cont‘d) public class  Container {  //  Ausschnitt! private   ...
Reportgenerator (8) Schritt 3: Realisiere DI via Reflection (cont‘d) <ul><li>Konfigurationsdatei: configuration.properties...
Reportgenerator (9) Schritt 4: Konfiguration mit Spring Beans (UML) <ul><li>Entkopplung, Schritt 4:  Verwende Spring Beans...
Reportgenerator (10) Schritt 4: Konfiguration mit Spring Beans (cont‘d) import  org.springframework.context.ApplicationCon...
Reportgenerator (10) Schritt 4: Konfiguration mit Spring Beans (cont‘d) <? xml   version = &quot;1.0&quot;   encoding = &q...
Beans & ihre Konfiguration in Spring
Begrifflichkeiten Spring und J2EE POJO vs. JavaBean vs. (Spring) Bean <ul><li>POJO (= Plain Old Java Object). Ein POJO ist...
<ul><li>Bean ==  POJO mit eindeutiger ID </li></ul><ul><li>Unterscheidung zweier Typen anhand des  scope   (= Gültigkeitsb...
Bean Definition (1) Bekanntmachen von Komponenten <ul><li>Eine  Bean Definition  macht Spring Komponenten bekannt </li></u...
<ul><li>< bean   id = &quot;exampleBean&quot;   class = &quot;org.example.ExampleBean&quot; > </li></ul><ul><li>< property...
Bean-Definition (3) Zum Beispiel gehörige Klassendefinition <ul><li>public   class  ExampleBean { </li></ul><ul><li>privat...
Konfiguration des Spring IoC-Containers BeanFactory vs. Application Context <ul><li>Konfiguration des IoC-Containers via  ...
Initialisierung des Spring IoC-Containers  Lokalisieren, Erzeugen und Verwalten von Beans <ul><li>Spring verwendet eine Be...
Erzeugung von Beans (1) Ablauf <ul><li>Ausgehend von Definitionen legt Spring Abhängigkeits-Digraphen an </li></ul><ul><li...
Erzeugung von Beans (2) Zeitpunkt der Initialisierung <ul><li>Scope  singleton  – werden bei Start des Containers angelegt...
Injizierung von Beans Ablauf <ul><li>Ausgangslage ist wieder der Abhängigkeitsgraph </li></ul><ul><li>Beans werden durch K...
Setzen von Bean-Attributen Bean Properties <ul><li>Häufigste Methode von DI: Injizierung via Properties </li></ul><ul><li>...
JavaBean Antipattern Überprüfen von gesetzten Attributen via Spring <ul><li>Beim Arbeiten mit JavaBeans wird ein „leeres“ ...
Lifecycle-Management von Beans via Interface <ul><li>Implementiere  InitializingBean  oder  OtherBean : </li></ul><ul><li>...
Lifecycle-Management von Beans via Konfiguration oder Annotation <ul><li>Konfiguration: </li></ul><ul><li>< bean   id = &q...
Zusammenfassung & Ressourcen
Spring Core (DI) Alternativen <ul><li>GoogleGuice:  http://code.google.com/p/google-guice /   </li></ul><ul><ul><li>unters...
Spring Framework Pros and Cons <ul><li>Für Dependency Injection andere starke Frameworks verfügbar </li></ul><ul><li>Sprin...
Literatur Webressourcen & Artikel <ul><li>[Tarr et al.  1999] Peri Tarr, Harold Ossher, William Harrison, and Stanley M. S...
Literatur Bücher zum Thema <ul><li>[Gamma et al.  1994]  Erich Gamma et al. (Gang of Four) Design Patterns Addison Wesley,...
Vielen Dank.
Upcoming SlideShare
Loading in...5
×

2009 03 17 Spring101

780

Published on

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
780
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "2009 03 17 Spring101"

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

    Clipping is a handy way to collect important slides you want to go back to later.

×