Komponenten-basierte Entwicklung Teil 11: Spring...
Transcript of Komponenten-basierte Entwicklung Teil 11: Spring...
12.11.14 1Komponenten – WS 2014/15 – Teil 11/Spring-DI
Komponenten-basierte Entwicklung
Teil 11: Spring - Dependency Injection
Komponenten – WS 2014/15 – Teil 11/Spring-DI 2
Literatur
[11-1] Wolff, Eberhard: Spring 3. 3. Auflage, 2010, dpunkt
[11-2] Walls, Craig: Spring im Einsatz. 2. Auflage, 2012, Hanser
[11-3] http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/pdf/spring-framework-reference.pdf
[11-4] http://docs.spring.io/spring-framework/docs/current/
[11-5] Winterfeldt, David: Spring by Example.http://www.springbyexample.org/examples/index.html
[11-6] http://start.spring.io/
[11-7] http://maven-repository.com/archetypes
Komponenten – WS 2014/15 – Teil 11/Spring-DI 3
Übersicht
• Konzept
• Hello-World: BigBean und SmallBean
• Setter-Injection mit Spring
• Mehrere Objekte derselben Klasse
• Constructor-Injection mit Spring
• Benutzung der eigenen Fabrik mit Setter-Injection
• Eigene Fabrik benutzt Spring
Komponenten – WS 2014/15 – Teil 11/Spring-DI 4
Spring – was ist das?
• Spring ist ein Container für Komponenten, der neben Dependency Injection weitere Pakete integriert, z.B.
– Hibernate
– AOP (Aspect Oriented Programming)
– MVC-Web
• In diesen Teil wird nur der Kern des Dependency Injection beschrieben.
• Das Ziel besteht im automatisierten Aufbau von Objekt-Geflechten.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 5
Spring – was ist das? - Begriffe
• POJO = Plain Old Java Object = Java Klasse analog zu
• MOJO = Maven Old Java Object
• Bean = POJO = Java Klasse mit bestimmten Aufbau:
– Set-Methoden für die Setter-Injection
– Konstruktoren mit Parameter für die Constructor-Injection
• Container = Laufzeitumgebung einschließlich Management
• Diese Vorgaben führen zu recht viel Boilerplate-Code.
• Boilerplate = eigentlich: Kochplatte = notwendiger, teilweise umfangreicher Code mit trivialer SemantikTypisch:
– Try-Catch-Orgien
– Getter/Setter-Orgien
• Siehe: http://de.wikipedia.org/wiki/Boilerplate
Komponenten – WS 2014/15 – Teil 11/Spring-DI 6
Spring – was ist das? - Struktur I
„Hauptprogramm“
Spring-DI
Spezifikation
call
read
In diesem Teil wird nur die XML-Datei basierte Version beschrieben.
Object 3
Object 1Object 4
Object 2
create
Komponenten – WS 2014/15 – Teil 11/Spring-DI 7
Spring – was ist das? - Struktur II
• Spring-DI ist eigentlich nichts anderes als eine durch eine Datei gesteuerte Factory.
• Es gibt noch die neuere Version mit Annotationen.
• Die Aufgabe besteht im Erzeugen und Binden (Linking) von Objekten zu Objekt-Geflechten:
– Jedes Objekt wird als Singleton realisiert, so dass damit Beans/Klassen mit Funktionalität behandelt werden.
– Es können auch mehrere Exemplare realisiert werden, so dass damit Beans/Klassen mit Daten behandelt werden.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 8
Spring – was ist das? - Konzept
Klassen
Spring-DI
Spezifikation
call
read
KlassenKlassen
SpezifikationSpezifikation
Objecterealize
container
Es wird ähnlich wie bei Mavenein Lifecycle realisiert.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 9
Maven und Spring I
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <spring.version>4.1.1.RELEASE</spring.version> … … …</properties>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version></dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version></dependency>
Komponenten – WS 2014/15 – Teil 11/Spring-DI 10
Maven und Spring II
<properties> … … … <package.name>de.htw_berlin.f4.kbe.spring</package.name> <main.name>App</main.name></properties>
… … … <artifactId>maven-jar-plugin</artifactId><version>2.4</version><configuration> <archive> <manifest> <mainClass>${package.name}.${main.name}</mainClass> <addClasspath>true</addClasspath> </manifest> </archive></configuration>… … …
Komponenten – WS 2014/15 – Teil 11/Spring-DI 11
Zwei Objekte werden verknüpft I - BigBean
public class BigBean { private SmallBean myBean; private int intProperty; BigBean() { System.out.println("*BIG bean is made*"); } public SmallBean getMyBean() { return myBean; } public void setMyBean(SmallBean myBean) { this.myBean= myBean; } public int getIntProperty() { return intProperty; } public void setIntProperty(int intProperty) { this.intProperty= intProperty; }}
Komponenten – WS 2014/15 – Teil 11/Spring-DI 12
Zwei Objekte werden verknüpft II - SmallBean
public class SmallBean { private String myName; SmallBean() { System.out.println("*small bean is made*"); } public String getMyName() { return myName; } public void setMyName(String myName) { this.myName= myName; }}
Komponenten – WS 2014/15 – Teil 11/Spring-DI 13
Zwei Objekte werden verknüpft III - Spring
<?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-4.1.xsd">
<bean id="IDBigBean" class="de.htw_berlin.f4.kbe.spring.BigBean"> <property name="intProperty"> <value>42</value> </property> <property name="myBean"> <ref bean="IDSmallBean"/> </property> </bean>
<bean id="IDSmallBean" class="de.htw_berlin.f4.kbe.spring.SmallBean"> <property name="myName"> <value>Ich bin das kleine Beanchen</value> </property> </bean> </beans>
Datei BigSmallBeans.xml
Komponenten – WS 2014/15 – Teil 11/Spring-DI 14
Erläuterungen I
<bean id="IDBigBean" class="de.htw_berlin.f4.kbe.spring.BigBean">
<property name="intProperty"> <value>42</value> </property>
<property name="myBean"> <ref bean="IDSmallBean"/> </property>
Name der Klassein Spring
Name der Klassein Java
Name desAttributs in Java
Wert desAttributs
Name desAttributs in Java
Referenz aufSpring Bean
Komponenten – WS 2014/15 – Teil 11/Spring-DI 15
Erläuterungen II
• Bei den einfachen Attributen wird mit der setter-Injektion gearbeitet: Entsprechend der Namenskonvention werden die set-Methoden mit dem Parameter versehen
• Bei Attributen mit einer Referenz erfolgt dasselbe.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 16
Zwei Objekte werden verknüpft IV - Hauptprogramm
import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App { public static void main(String[] args) { System.out.println("Hello Beans!"); ApplicationContext appContext= new ClassPathXmlApplicationContext("BigSmallBeans.xml"); BigBean big= (BigBean) appContext.getBean("IDBigBean"); SmallBean small= big.getMyBean(); System.out.println("big.getIntProperty()= "+big.getIntProperty()); System.out.println("small.getMyName() = "+small.getMyName()); }}
Komponenten – WS 2014/15 – Teil 11/Spring-DI 17
Erläuterungen
ApplicationContext appContext= new ClassPathXmlApplicationContext("BigSmallBeans.xml")
Name der Spring-Konfigurationsdatei
BigBean big= (BigBean) appContext.getBean("IDBigBean");
Es wird ein Container für das Objekt-Geflecht eingerichtet.
Basierend auf der Container-Initialisierung wird das Geflecht in Form eines Singletons aufgebaut und initialisiert.
Name der Klassein Spring
Komponenten – WS 2014/15 – Teil 11/Spring-DI 18
Zwei Objekte werden verknüpft V - Output
Hello Beans!Nov 10, 2014 8:43:25 PM org.springframework.... prepareRefreshINFORMATION: Refreshing org.springframework....: startup date … Nov 10, 2014 8:43:25 PM org.springframework.... loadBeanDefinitionsINFORMATION: Loading XML bean definitions ... [BigSmallBeans.xml]*BIG bean is made**small bean is made*big.getIntProperty()= 42small.getMyName() = Ich bin das kleine Beanchen
Output
Komponenten – WS 2014/15 – Teil 11/Spring-DI 19
Netbeans Integration
Klassen – wie immer
Konfigurationsdateien
POM und netbeans-Konfiguration
Komponenten – WS 2014/15 – Teil 11/Spring-DI 20
Variation I – Ort der XML-Datei
ClassPathXmlApplicationContext("BigSmallBeans.xml");
XML-Datei muss ander Target-Wurzel liegen.
ClassPathXmlApplicationContext("de/htw_berlin/f4/kbe/spring/BigSmallBeans.xml");
XML-Datei muss im Klassen-Ordner liegen.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 21
Variation II – Ort der XML-Datei
Es kann auch der absolute Pfad zur XML-Datei angegeben werden.
import org.springframework.context.support.FileSystemXmlApplicationContext;… … … String fn= "D:/bmesser/.../Spring-01/target/classes/BigSmallBeans.xml";ApplicationContext appContext= new FileSystemXmlApplicationContext(fn);
Komponenten – WS 2014/15 – Teil 11/Spring-DI 22
Singleton
• Singleton = Objekt, das nur ein einziges Mal erzeugt werden kann
• Spring erzeugt per Default nur Singletons ohne dass das Singelton-Muster benutzt wird.
• Siehe:
– http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)
– http://de.wikipedia.org/wiki/Liste_von_Singleton-Implementierungen
BigBean big= (BigBean) appContext.getBean("IDBigBean");...BigBean big2= (BigBean) appContext.getBean("IDBigBean");System.out.println("Dieselben Objekte? "+(big==big2));
Output
Dieselben Objekte? true
Komponenten – WS 2014/15 – Teil 11/Spring-DI 23
Der Event Manager noch einmal I
Location DescriptionEventAppointment
• Location: Liste der Orte
• Event: Liste der Aktivitäten
• Description: Beschreibung der Aktivität
• Appointment: Zusammenfassung samt Datum und Uhrzeit
• Es werden alle Klassen systematisch mit getXXX/setXXX()-Methoden versehen.
• Es werden alle Konstruktoren auf den Standard-Konstruktor ohne Parameter reduziert.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 24
Der Event Manager noch einmal II
public class Event { EventType mode; Description description; public void setMode(EventType mode) { this.mode= mode; } public EventType getMode() { return this.mode; } public void setDescription(Description description) { this.description= description; } public Description getDescription() { return this.description; }}
Hier nur als Beispiel die Klasse Event.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 25
Der Event Manager noch einmal III
public class Appointment { String date; String time; Location location; Event event; public void setLocation(Location location) { this.location= location; } public void setEvent(Event event) { this.event= event; } public String getStreet() { return location.getStreet(); } public void setStreet(String street) { location.setStreet(street); }
Dies ist der 1. Teil von Appointment.Mit den get/set-Methoden wird der innere Aufbau verdeckt.
Routinen, dievon Springbeim Zusammen-bau aufgerufenwerden.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 26
Der Event Manager noch einmal IV
public EventType getMode() { return event.getMode(); } public void setMode(EventType mode) { event.setMode(mode); } public String getDescription() { return event.getDescription().getDescription(); } public void setDescription(String text) { event.getDescription().setDescription(text); }} Bei jedem Zwischenschritt
eines Zugriffs werdendie get/set-Routinen benutzt.
Dies ist der 2. Teil von Appointment (Auszug).
Komponenten – WS 2014/15 – Teil 11/Spring-DI 27
Der Event Manager noch einmal V - XMLContext
<bean id="IDApps" class="de.htw_berlin.f4.kbe.spring.Appointment"> <property name="location"> <ref bean="IDLocation"/> </property> <property name="event"> <ref bean="IDEvent"/> </property> <property name="street"> <value>Müllerstr.</value> </property> <property name="houseNumber"> <value>12a</value> </property> <property name="city"> <value>Berlin</value> </property> <property name="postalCode"> <value>11089</value> </property> <property name="mode"> <value>BIRTHDAY</value> </property> <property name="description"> <value>Geburtstag ...</value> </property> <property name="date"> <value>10. Mai 2012</value> </property> <property name="time"> <value>19:00</value> </property></bean><bean id="IDLocation" class="de.htw_berlin.f4.kbe.spring.Location"/><bean id="IDEvent" class="de.htw_berlin.f4.kbe.spring.Event"> <property name="description"> <ref bean="IDDescription"/> </property></bean> <bean id="IDDescription" class="de.htw_berlin.f4.kbe.spring.Description"/>
Auszug aus der XML-DateiEs werden alle Attribute über die Zugriffsfunktionen von Appointment gesetzt
Komponenten – WS 2014/15 – Teil 11/Spring-DI 28
Der Event Manager noch einmal VI
public class EventManager { Appointment[] apps; EventManager() { apps= new Appointment[10]; ApplicationContext appContext= new ClassPathXmlApplicationContext("Feten.xml"); apps[0]= (Appointment) appContext.getBean("IDApps"); } protected void printAppointments() { for(Appointment app : apps) { if(app!=null) { System.out.printf( "Am %s %s: %s Ort %s %s %s %s ist %s\n", app.getDate(),app.getTime(), app.getMode(), app.getStreet(), app.getHouseNumber(),app.getPostalCode(), app.getCity(), app.getDescription());}}}}
Das „Hauptprogramm“; die Initialisierung erfolgt über Spring.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 29
Der Event Manager noch einmal VII
• Damit ist ein Satz von Objekten erzeugt und vorbelegt.
• Per XML ist das nur für ein Geflecht möglich.
• D.h. wir bauen um...
Output
Liste der Feten 2012Nov 11, 2014 3:39:59 PM org.springframework.context....INFORMATION: Refreshing org.springframework.context....Nov 11, 2014 3:39:59 PM org.springframework.beans.factory.xml....INFORMATION: Loading XML bean definitions from ... [Feten.xml]Am 10. Mai 2012 19:00: BIRTHDAY Ort Müllerstr. 12a 11089 Berlin ist ...
Komponenten – WS 2014/15 – Teil 11/Spring-DI 30
Events zum Dritten I
<bean id="IDApps" class="de.htw_berlin.f4.kbe.spring.Appointment"> <property name="location"> <ref bean="IDLocation"/> </property> <property name="event"> <ref bean="IDEvent"/> </property></bean>
<bean id="IDLocation" class="de.htw_berlin.f4.kbe.spring.Location"/>
<bean id="IDEvent" class="de.htw_berlin.f4.kbe.spring.Event"> <property name="description"> <ref bean="IDDescription"/> </property></bean>
<bean id="IDDescription" class="de.htw_berlin.f4.kbe.spring.Description"/>
Das Setzen der Daten wird aus der XML-Datei entfernt und es ineine Art „Loader“ in Appointment verschoben.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 31
Events zum Dritten II
public class EventManager { Appointment[] apps; EventManager() { apps= new Appointment[10]; init(); } private void init() { ApplicationContext appContext= new ClassPathXmlApplicationContext("Feten.xml"); apps[0]= (Appointment) appContext.getBean("IDApps"); apps[0].setStreet("Müllerstr."); apps[0].setHouseNumber("12a"); apps[0].setCity("Berlin"); apps[0].setPostalCode("11089"); apps[0].setMode(EventType.BIRTHDAY); apps[0].setDescription("Geburtstag des grossen Vorsitzenden"); apps[0].setDate("10. Mai 2012"); apps[0].setTime("19:00");
Der 1. Teil
Komponenten – WS 2014/15 – Teil 11/Spring-DI 32
Events zum Dritten II
apps[1]= (Appointment) appContext.getBean("IDApps"); apps[1].setStreet("Karl-May-Allee"); apps[1].setHouseNumber("110"); apps[1].setCity("Berlin"); apps[1].setPostalCode("12017"); apps[1].setMode(EventType.BOOZY_PARTY); apps[1].setDescription("Gelage bei Willi"); apps[1].setDate("1. April 2012"); apps[1].setTime("18:00"); }
Der 2. Teil
Output
Liste der Feten 2012Nov 11, 2014 3:49:12 PM org.springframework.....INFORMATION: Refreshing org.springframework.....Nov 11, 2014 3:49:12 PM org.springframework.....INFORMATION: Loading XML bean definitions from... [Feten.xml]Am 1. April 2012 18:00: BOOZY_PARTY Ort Karl-May-Allee 110 12017 Berlin ...Am 1. April 2012 18:00: BOOZY_PARTY Ort Karl-May-Allee 110 12017 Berlin ...
Und das ist falsch.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 33
Events zum Dritten III
<bean id="IDApps" class="de.htw_berlin.f4.kbe.spring.Appointment" scope="prototype"> <property name="location"> <ref bean="IDLocation"/> </property> <property name="event"> <ref bean="IDEvent"/> </property></bean>
Mit diesem Attribute wird jeweils ein neues Objekt geschaffen.
Output
Am 10. Mai 2012 19:00: BOOZY_PARTY Ort Karl-May-Allee 110 12017 Berlin ist ...Am 1. April 2012 18:00: BOOZY_PARTY Ort Karl-May-Allee 110 12017 Berlin ist ...
Immer noch falsch.
Richtig, da Appointmentdupliziert wird.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 34
Events zum Dritten IV
EventManager
Appoint-ment
Event
Location
Description
EventManager
Appoint-ment
Event
Location
Description
Appoint-ment
Vorher (Falsch)
Nachher (Falsch)
Alles benötigt scope=“prototype“.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 35
Events zum Dritten V
Am 10. Mai 2012 19:00: BIRTHDAY Ort Müllerstr. 12a 11089 Berlin ist ...Am 1. April 2012 18:00: BOOZY_PARTY Ort Karl-May-Allee 110 12017 ...
EventManager
Appoint-ment
Event
Location
DescriptionNun richtig.
Appoint-ment
Event
Location
Description
Output
Das ist der Unterschiedzwischen dem flachenund dem tiefen Klonen.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 36
Eine Variation – Constructor Injection I
<bean id="IDApps" class="de.htw_berlin.f4.kbe.spring.Appointment"scope="prototype">
<constructor-arg ref="IDLocation"/> <constructor-arg ref="IDEvent"/></bean><bean id="IDLocation" class="de.htw_berlin.f4.kbe.spring.Location"
scope="prototype"/><bean id="IDEvent" class="de.htw_berlin.f4.kbe.spring.Event"
scope="prototype"> <constructor-arg ref="IDDescription"/></bean> <bean id="IDDescription" class="de.htw_berlin.f4.kbe.spring.Description"
scope="prototype"/>
Anstatt mit setXXX() die Verknüpfungen zu realisieren, werden diese mit dem Konstruktor gesetzt.Daher müssen die Klassen Appointment und Event geändert werden.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 37
Eine Variation – Constructor Injection II
public class Appointment { String date; String time; Location location; Event event; Appointment(Location location,Event event) { this.location= location; this.event= event; } public void setDate(String date) { this.date= date; } public String getDate() { return this.date; }… … …
Der Konstruktor erwartet die Referenzen auf die anderen Objekte. Anhand des Typs erkennt Spring, was zu welchem Parameter gehört.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 38
Eine Variation – Constructor Injection III
public class Event { EventType mode; Description description; Event(Description description) { this.description= description; } public void setMode(EventType mode) { this.mode= mode; }… … …
Komponenten – WS 2014/15 – Teil 11/Spring-DI 39
Eine Variation – Eigene Fabrik I
public class Appointment extends AbstractAppointment { static AppointmentCreation factory;
Appointment(Location location, Event event) { super(location,event); } Appointment() { } public static void setFactory(AppointmentCreation newFactory) { factory= newFactory; }
• Es wird die alte Implementierung aus der Einheit über Dependency Injection genommen.
• Dort gab es zwei Factories, die über ein statisches Attribut innerhalb der Klasse Appointment aufgerufen werden.
• Dieses Attribut wird nun per Setter-Injektion mit Spring gesetzt.
1. Teil vonAppointment
Set-Routine für Spring
Komponenten – WS 2014/15 – Teil 11/Spring-DI 40
Eine Variation – Eigene Fabrik II
public static Appointment newObject(int record) { Appointment app= factory.createAppointment(); switch (record) { case 0: app.setStreet("Müllerstr."); app.setHouseNumber("12a"); app.setCity("Berlin"); app.setPostalCode("11089"); app.setMode(EventType.BIRTHDAY); app.setDescription("Geburtstag des grossen Vorsitzenden"); app.setDate("10. Mai 2012"); app.setTime("19:00"); break; case 1: … … … } return app;}}
2. Teil vonAppointment
Aufruf derFactory
Komponenten – WS 2014/15 – Teil 11/Spring-DI 41
Eine Variation – Eigene Fabrik III
public class EventManager { Appointment[] apps; EventManager() { apps= new Appointment[10]; ApplicationContext appContext= new ClassPathXmlApplicationContext("Feten_Factory.xml"); apps[0]= (Appointment) appContext.getBean("IDApps"); apps[0]= Appointment.newObject(0); apps[1]= Appointment.newObject(1); }… … …
Aufruf derFactory
Injection
public class App { public static void main( String[] args ) { System.out.println("Liste der Feten 2012"); EventManager ev= new EventManager(); ev.printAppointments(); }}
Hier das gleiche„Hauptprogramm“
Komponenten – WS 2014/15 – Teil 11/Spring-DI 42
Eine Variation – Eigene Fabrik IV
<bean id="IDApps" class="de.htw_berlin.f4.kbe.spring.Appointment"> <property name="factory"> <ref bean="IDFactory"/> </property></bean><bean id="IDFactory" class="de.htw_berlin.f4.kbe.spring.AppointmentFactory"/><bean id="IDAltFactory" class="de.htw_berlin.f4.kbe.spring.AppointmentAlternativeFactory"/>
Output
Liste der Feten 2012Nov 11, 2014 6:04:43 PM org.springframework....INFORMATION: Refreshing org.springframework....Nov 11, 2014 6:04:43 PM org.springframework....INFORMATION: Loading XML bean definitions from ... [Feten_Factory.xml]AppointmentFactory is usedAppointmentFactory is usedAm 10. Mai 2012 19:00: BIRTHDAY Ort Müllerstr. 12a 11089 Berlin ist ...Am 1. April 2012 18:00: BOOZY_PARTY Ort Karl-May-Allee 110 12017 Berlin ...
Komponenten – WS 2014/15 – Teil 11/Spring-DI 43
Bemerkungen I
• newObject() ist eine statische Routine, die über eine statische Referenzvariable factory aufgerufen wird.
• Daher wird bei Appointment nicht mit scope=“prototype“ gearbeitet, denn aus der Sicht von Spring ist Appointment ein Singleton.
• In diesem Singleton erzeugt die eigene Factory newObject() per new() neue Instanzen.Oder anders formuliert: Die (nicht-statische) Klasse Appointment hat eine eigene statische Factory, um eine Instanz von sich selbst zu erzeugen.
• Factories werden grundsätzlich nur einmal instanziiert.
Diese Konstruktion ist ein bischen tricky...
Komponenten – WS 2014/15 – Teil 11/Spring-DI 44
Bemerkungen II
Datei fürProduktion
Datei für dasTesten (mit Mocks)
Je nach Anwendungsfall wird eine andereFabrik-Methode gewählt.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 45
Noch eine Variation – Eigene Fabrik I
Es ist auch möglich, dass Spring die Factory angegeben wird:
<bean id="IDApps" class="de.htw_berlin.f4.kbe.spring.Appointment" factory-method="newObject" scope="prototype"></bean>
Oder eben:
<bean id="IDApps" class="de.htw_berlin.f4.kbe.spring.Appointment" factory-method="newObjectAlternate" scope="prototype"></bean>
Dazu muss es zwei Factory-Methoden geben.Wir bauen das Programm um...
Komponenten – WS 2014/15 – Teil 11/Spring-DI 46
Noch eine Variation – Eigene Fabrik II
public class Appointment extends AbstractAppointment { static AppointmentCreation factoryNormal= new AppointmentFactory(); static AppointmentCreation factoryAltern= new AppointmentAlternativeFactory();
Appointment(Location location, Event event) { super(location,event); } Appointment() { } public static Appointment newObject() { return factoryNormal.createAppointment(); } public static Appointment newObjectAlternate() { return factoryAltern.createAppointment(); }}
Wir entfernen die Initialisierung und definieren zwei Erzeugungsmethoden.
Die beidenFactories
Hier werdensie erzeugt
Komponenten – WS 2014/15 – Teil 11/Spring-DI 47
Noch eine Variation – Eigene Fabrik III
public class EventManager { Appointment[] apps; EventManager() { apps= new Appointment[10]; ApplicationContext appContext= new ClassPathXmlApplicationContext("Feten_Factory.xml"); apps[0]= (Appointment) appContext.getBean("IDApps"); init(apps[0], 0); apps[1]= (Appointment) appContext.getBean("IDApps"); init(apps[1], 1); }
Spring ruft jetzt die Factory-Methoden auf.Bitte beachten: scope=“prototype“.
Hier werdensie erzeugt
1. Teil
Komponenten – WS 2014/15 – Teil 11/Spring-DI 48
Noch eine Variation – Eigene Fabrik IV
private void init(Appointment app, int record) { switch (record) { case 0: app.setStreet("Müllerstr."); app.setHouseNumber("12a"); app.setCity("Berlin"); app.setPostalCode("11089"); app.setMode(EventType.BIRTHDAY); app.setDescription("Geburtstag des grossen Vorsitzenden"); app.setDate("10. Mai 2012"); app.setTime("19:00");… … …
Das ist die heraus gezogene Initialisierungsroutine, dienun als Parameter ein Appointment-Objekt erhält.
2. Teil
Komponenten – WS 2014/15 – Teil 11/Spring-DI 49
Neugier I
DumpTree dump= new DumpTree();apps= new Appointment[10];ApplicationContext appContext = new ClassPathXmlApplicationContext("Feten_Factory.xml");apps[0]= (AbstractAppointment) appContext.getBean("IDApps");init(apps[0], 0);dump.showObject(apps[0]);apps[1]= (AbstractAppointment) appContext.getBean("IDApps");init(apps[1], 1);dump.showObject(apps[1]);… … …
Auszug ausEventManager
Als neugierige Menschen schauen wir uns genau an, was Springeigentlich gemacht hat.Dazu schreiben wir uns eine kleine Dump-Klasse, die das Objekt-geflecht traversiert und „graphisch“ ausgibt.
Komponenten – WS 2014/15 – Teil 11/Spring-DI 50
Neugier II - Ausgabe
Appointment AppointmentCreation factoryNormal= @62ee68d8 | +>AppointmentFactory AppointmentCreation factoryAltern= @58651fd0 | +>AppointmentAlternativeFactory String date= '10. Mai 2012' String time= '19:00' Location location= @5419f379 | +>Location String street= 'Müllerstr.' String houseNumber= '12a' String city= 'Berlin' String postalCode= '11089' Event event= @d2cc05a | +>Event EventType mode= [BIRTHDAY] Description description= @548a9f61 | +>Description String text= 'Geburtstag des grossen Vorsitzenden'
Das ist die Ausgabe des ersten Aufrufs
Einen Preis bekommtdas nicht – aber eserfüllt die Aufgabe
Komponenten – WS 2014/15 – Teil 11/Spring-DI 51
Nach dieser Anstrengung etwas Entspannung...