59
Spring Framework Jens Rühmkorf Tech Talk, DLR Köln-Porz, 17. März 2009

2009 03 17 Spring101

Embed Size (px)

Citation preview

Page 1: 2009 03 17 Spring101

Spring Framework

Jens Rühmkorf Tech Talk, DLR Köln-Porz, 17. März 2009

Page 2: 2009 03 17 Spring101

Folie 2Spring Framework > J. Rühmkorf > 17. März 2009

Inhalt

Überblick und Einführung

Grundlegende Prinzipien

Funktionsweise eines DI-Frameworks am Beispiel

Beans & ihre Konfiguration in Spring

Page 3: 2009 03 17 Spring101

Überblick und Einführung

Page 4: 2009 03 17 Spring101

Folie 4Spring Framework > J. Rühmkorf > 17. März 2009

Spring FrameworkGeschichte

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)

Page 5: 2009 03 17 Spring101

Folie 5Spring Framework > J. Rühmkorf > 17. März 2009

Spring FrameworkAnforderungen 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)

Page 6: 2009 03 17 Spring101

Folie 6Spring Framework > J. Rühmkorf > 17. März 2009

Übersicht des Spring Frameworkshttp://static.springframework.org/spring/docs/2.5.x/reference/

Page 7: 2009 03 17 Spring101

Folie 7Spring Framework > J. Rühmkorf > 17. März 2009

Spring Hello (1)Hello World!

public class HelloWorld {

private String message;

public void setMessage(String message) {

this.message = message;

}

public void hello() {

System.out.println("Hello! " + message);

}

}

class HelloWorld

HelloW orld

- message: String

+ hello() : void+ setMessage(String) : void

Main

+ main(String[]) : void

Page 8: 2009 03 17 Spring101

Folie 8Spring 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(); }}

Page 9: 2009 03 17 Spring101

Folie 9Spring 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>

Page 10: 2009 03 17 Spring101

Folie 10Spring 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

obtainFreshBeanFactoryINFO: 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!

Page 11: 2009 03 17 Spring101

Grundlegende Prinzipien

Page 12: 2009 03 17 Spring101

„Separation of

Concerns“(Dijkstra, 1974)

Page 13: 2009 03 17 Spring101

Folie 13Spring Framework > J. Rühmkorf > 17. März 2009

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)

Page 14: 2009 03 17 Spring101

Folie 14Spring 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

Page 15: 2009 03 17 Spring101

Folie 15Spring 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

Page 16: 2009 03 17 Spring101

Folie 16Spring Framework > J. Rühmkorf > 17. März 2009

Inversion of Control (4)Typische Einsatzgebiete

Benutzeroberflächen

Netzwerkdienste

Systemdienste, die System- bzw. Hardwareereignisse überwachen

Page 17: 2009 03 17 Spring101

Folie 17Spring 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 bereitDer IoC-Container injiziert die „Dependency“ buchstäblichkurz: DI

BemerkungFowler 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

Page 18: 2009 03 17 Spring101

Folie 18Spring 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

Page 19: 2009 03 17 Spring101

Folie 19Spring Framework > J. Rühmkorf > 17. März 2009

Dependency Lookup (1)Dependency Pull

Bekannteste Form von IoC

Lese Abhängigkeiten von einer (zentralen) Registry

Page 20: 2009 03 17 Spring101

Folie 20Spring Framework > J. Rühmkorf > 17. März 2009

public void start(BundleContext context) { this.context = context;}public String getCustomerName(long id) { ServiceReference ref = context.getServiceReference( ILookupService.class.getName()); if(ref != null) { ILookupService lookup = (ILookupService)

context.getService(ref); if(lookup != null) { Customer customer = lookup.findById(id); context.ungetService(ref); return customer.getName(); } } return null;}

Dependency Lookup (2)Dependency Pull am Beispiel von OSGi

zur Kommunikation mit zentraler „Service Registry“

verwende Service

schlage Service nach

Page 21: 2009 03 17 Spring101

Folie 21Spring 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);

}

Page 22: 2009 03 17 Spring101

Folie 22Spring 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 {

private Dependency dep;

public void performLookup(Container container) {

this.dep = (Dependency) container.getDependency("myDependency");

}

}

Aufruf durch Container

Page 23: 2009 03 17 Spring101

Folie 23Spring 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)

Page 24: 2009 03 17 Spring101

Folie 24Spring 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;

}

}

Page 25: 2009 03 17 Spring101

Folie 25Spring 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;

}

}

Page 26: 2009 03 17 Spring101

Funktionsweise eines DI-Frameworks am Beispiel

Page 27: 2009 03 17 Spring101

Folie 27Spring Framework > J. Rühmkorf > 17. März 2009

Arbeitsweise des FrameworksBeispiel: ein Reportgenerator

Aufgabe: erzeuge Reports in HTML oder PDF

Separiere Schnittstelle und Implementierung über ein Interface

Dienst wird über einen ReportService bereitgestellt

class Übersicht

HtmlReportGenerator

+ generate(String[][]) : void

PdfReportGenerator

+ generate(String[][]) : void

«interface»ReportGenerator

+ generate(String[][]) : void

ReportServ ice

+ generateAnnualReport(int) : void+ generateDailyReport(int, int, int) : void+ generateMonthlyReport(int, int) : void

Page 28: 2009 03 17 Spring101

Folie 28Spring 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

}

Page 29: 2009 03 17 Spring101

Folie 29Spring 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

HtmlReportGenerator

+ generate(String[][]) : void

PdfReportGenerator

+ generate(String[][]) : void

«interface»ReportGenerator

+ generate(String[][]) : void

ReportServ ice

+ generateAnnualReport(int) : void+ generateDailyReport(int, int, int) : void+ generateMonthlyReport(int, int) : void

Page 30: 2009 03 17 Spring101

Folie 30Spring Framework > J. Rühmkorf > 17. März 2009

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);

}

}

Reportgenerator (3)Schritt 1: Führe Container ein (cont‘d)

Page 31: 2009 03 17 Spring101

Folie 31Spring 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

+ Container()+ getComponent(String) : Object

HtmlReportGenerator

+ generate(String[][]) : void

PdfReportGenerator

+ generate(String[][]) : void

«interface»ReportGenerator

+ generate(String[][]) : void

ReportServ ice

+ generateAnnualReport(int) : void+ generateDailyReport(int, int, int) : void+ generateMonthlyReport(int, int) : void

Serv iceLocator

+ getReportGenerator() : ReportGenerator

Page 32: 2009 03 17 Spring101

Folie 32Spring Framework > J. Rühmkorf > 17. März 2009

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

}

Reportgenerator (5)Schritt 2: Verwende Service-Locator Pattern (cont‘d)

Page 33: 2009 03 17 Spring101

Folie 33Spring 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

HtmlReportGenerator

+ generate(String[][]) : void

PdfReportGenerator

+ generate(String[][]) : void

«interface»ReportGenerator

+ generate(String[][]) : void

ReportServ ice

+ generateAnnualReport(int) : void+ generateDailyReport(int, int, int) : void+ generateMonthlyReport(int, int) : void

Page 34: 2009 03 17 Spring101

Folie 34Spring Framework > J. Rühmkorf > 17. März 2009

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);

}

}

}

Reportgenerator (7)Schritt 3: Realisiere DI via Reflection (cont‘d)

Page 35: 2009 03 17 Spring101

Folie 35Spring Framework > J. Rühmkorf > 17. März 2009

# 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

Reportgenerator (8)Schritt 3: Realisiere DI via Reflection (cont‘d)

Konfigurationsdatei: configuration.properties

Verwendet BeanUtils aus Apache Commons

Page 36: 2009 03 17 Spring101

Folie 36Spring 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

HtmlReportGenerator

+ generate(String[][]) : void

PdfReportGenerator

+ generate(String[][]) : void

«interface»ReportGenerator

+ generate(String[][]) : void

ReportServ ice

+ generateAnnualReport(int) : void+ generateDailyReport(int, int, int) : void+ generateMonthlyReport(int, int) : void

Page 37: 2009 03 17 Spring101

Folie 37Spring Framework > J. Rühmkorf > 17. März 2009

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);

}

}

Reportgenerator (10)Schritt 4: Konfiguration mit Spring Beans (cont‘d)

Page 38: 2009 03 17 Spring101

Folie 38Spring 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>

Page 39: 2009 03 17 Spring101

Beans & ihre Konfiguration in Spring

Page 40: 2009 03 17 Spring101

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

Begrifflichkeiten Spring und J2EEPOJO vs. JavaBean vs. (Spring) Bean

POJO (= Plain Old Java Object). Ein POJO ist ein „simples“ Java Objekt, das:

1. Keine vorgegebenen Klassen erweitert,

2. keine vorgegebenen Interfaces implementiert,

3. keine vorgegebenen Annotations enthält.

– JavaBean (J2EE Kontext): Ein JavaBean ist ein POJO das:

1. Öffentlichen Standardkonstruktor besitzt,

2. serialisierbar ist,

3. öffentliche Getter/Setter-Methoden besitzt.

– Spring Beans:

Komponenten heißen in Spring Beans.

Beans == POJOs.

Page 41: 2009 03 17 Spring101

Folie 41Spring Framework > J. Rühmkorf > 17. März 2009

Bean == POJO mit eindeutiger IDUnterscheidung zweier Typen anhand des scope (= Gültigkeitsbereich)

singletonEine Instanz wird angelegt & referenziert bei jedem Zugriff

prototype (nicht-singleton)neue Bean wird jedes Mal erzeugtanalog zu new KlassenName()

Weiter Typen bei Web- und Portal-Applikationen (ab Spring 2.x):request, session, globalSessionSpring legt Beans i.d.R. so spät wie möglich an

Komponenten in SpringSpring Beans

Page 42: 2009 03 17 Spring101

Folie 42Spring 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

Page 43: 2009 03 17 Spring101

Folie 43Spring Framework > J. Rühmkorf > 17. März 2009

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

Bean Definition (2)Beispiel einer XML-Konfiguration

Page 44: 2009 03 17 Spring101

Folie 44Spring 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; }}

Page 45: 2009 03 17 Spring101

Folie 45Spring Framework > J. Rühmkorf > 17. März 2009

Konfiguration des Spring IoC-ContainersBeanFactory 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

Page 46: 2009 03 17 Spring101

Folie 46Spring 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 Beanszu lokalisieren, zu erzeugen und zu verwalten

Typischerweise verwendet man eine XML-BeanFactory:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

Page 47: 2009 03 17 Spring101

Folie 47Spring 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

Page 48: 2009 03 17 Spring101

Folie 48Spring 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");

Page 49: 2009 03 17 Spring101

Folie 49Spring Framework > J. Rühmkorf > 17. März 2009

Injizierung von BeansAblauf

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;

Page 50: 2009 03 17 Spring101

Folie 50Spring Framework > J. Rühmkorf > 17. März 2009

Setzen von Bean-AttributenBean Properties

Häufigste Methode von DI: Injizierung via PropertiesInjiziert 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>

Page 51: 2009 03 17 Spring101

Folie 51Spring 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“ wirdZustand ist erst valide nach Aufruf aller oder mindestens einiger SetterÜberprüfung per Konfiguration:none*, simple, objects, allAnnotation der Setter-Methoden mit @Resource: (einschalten via <context:annotation-config/>)@Requiredpublic void setMessage(String message) { this.message = message;}@Requiredpublic void setValue(int value) { this.value = value;}

Page 52: 2009 03 17 Spring101

Folie 52Spring Framework > J. Rühmkorf > 17. März 2009

Lifecycle-Management von Beansvia 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(); }}

Page 53: 2009 03 17 Spring101

Folie 53Spring Framework > J. Rühmkorf > 17. März 2009

Lifecycle-Management von Beansvia 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:@PreDestroyprivate void closeResource() { System.out.println("close resource");}@PostConstructprivate void openResource() { System.out.println("open resource");}

Page 54: 2009 03 17 Spring101

Zusammenfassung & Ressourcen

Page 55: 2009 03 17 Spring101

Folie 55Spring Framework > J. Rühmkorf > 17. März 2009

Spring Core (DI)Alternativen

GoogleGuice: http://code.google.com/p/google-guice/ unterstützt DI via Annotationsviel „Autowiring“klein & schnellkeine Unterstützung von Lifecycles (dazu: GuiceyFruit)

PicoContainer: http://www.picocontainer.org/ unterstützt DI von Typ 2+3 sowie unterstützt DI mittels AnnotationsUnterstützung von Lifecyclesklein: ~260K, etabliert

Weitere Frameworks: Java-Source.nethttp://java-source.net/open-source/containers

Page 56: 2009 03 17 Spring101

Folie 56Spring Framework > J. Rühmkorf > 17. März 2009

Spring FrameworkPros 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

Page 57: 2009 03 17 Spring101

Folie 57Spring Framework > J. Rühmkorf > 17. März 2009

LiteraturWebressourcen & Artikel

[Tarr et al. 1999]Peri Tarr, Harold Ossher, William Harrison, and Stanley M. Sutton, Jr.N Degrees of Separation: Multi-dimensional Separation of ConcernsIntl. Conf. on Software Engineering (ICSE-11, 1999)http://dx.doi.org/10.1145/302405.302457

[Foote, and Yoder 1997]Brian Foote, and Joseph YoderBig Ball of Mud4th Conf. on Patterns Languages of Programs (PLoP ’97)http://www.laputan.org/mud/

[Fowler 2004] Martin FowlerInversion of Control Containers and the Dependency Injection Patternmartinfowler.com, Januar 2004http://www.martinfowler.com/articles/injection.html

[Weiskotten 2006] Jeremy WeiskottenDependency Injection & Testable ObjectsDr. Dobbs Journal, April 2006http://www.ddj.com/185300375

Page 58: 2009 03 17 Spring101

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

LiteraturBücher zum Thema

[Gamma et al. 1994] Erich Gamma et al. (Gang of Four)Design PatternsAddison Wesley, November 1994

[Mak 2008] Gary MakSpring RecipesApress, Juni 2008

Page 59: 2009 03 17 Spring101

Vielen Dank.