Spring Dependency Injection - XML oder Annotations?

DarthShader

Erfahrenes Mitglied
Hallo,

ich würde gerne einmal Eure Meinung zu Dependency Injection in Spring hören. Ich habe mittlerweile eine stattlichen Application Context aufgebaut, mit einer menge Services, die anderen injiziert werden etc. Diese XML Konfiguration ist schon relativ groß, und damit auch unübersichtlich, obwohl ich eine Aufteilung in mehrere XML Dateien habe (trennung von technischen und fachlichen Klassen, Views und Controllern, Validation etc.).

Ich würde mich dennoch als Anfänger in Sachen Spring IoC bezeichnen, da ich es erst in einem Projekt eingesetzt habe. Nun habe ich mir gerade die Kapitel der offiziellen Spring (Online-) Dokumentation zur Annotation Based Configuration durchgelesen.

Ich will hier natürlich keinen Glaubenskrieg losbrechen, gerade im Bereich Enterprise Entwicklung gibt es ja Vor- und Nachteile für Annotationen (nicht nur bei Dep. Inj.), aber ich würde dennoch gerne mal hören, ob ihr Annotations für Springs Dependency Injection bevorzugt, oder eher die XML Konfiguration. Für mich ist das gerade sehr reizvoll, alle Injections auf Annotations umzustellen, um meine XML Konfiguration übersichtlicher zu halten, möchte ich aber vor eventuelle Fallstricke bewahren (wenn es welche gibt), bevor ich anfange, alles umzustellen.

Was meint ihr?


Vielen Dank für Eure Hilfe
 
Hm, das ist wirklich eine Glaubensfrage. Allerdings kann man der mit ein paar Heuristiken begegnen:

1. Wenn "es" sich ändert gehört es ins XML.

Schon hierbei ist es schwierig zu definieren was "sich ändern" bedeutet. Transaktionen kann man z.B. bequem über Annotationen definieren, es wird wohl kaum jemand während des Betriebs auf die Idee kommen, die Transaktionskonfiguration ändern zu wollen. Das wiring der Komponenten mit @Autowired ist schon eine schwierigere Sache: hier sollte man sich vor allem Fragen mit welcher Konfigurationsart das Team am besten vertraut ist. Besonders beim Autowiring entsteht schnell die Frage, warum etwas wie gewired wird und was passiert, wenn die Referenz nicht mehr eindeutig aufgelöst werden kann. Mit diesen Situationen sollte man dann umgehen können.

Beim WebMVC fine ich die neue annotationsbasierte Konfiguration besser als die alte. Vor allem wegen der größeren Testbarkeit. Allerdings zieht man sich hier auch einen Haufen "Magic" herbei, der den Entwicklern bewusst sein sollte. Es hilft nichts wenn einer ales durchblickt und der Rest nur drumrumarbeitet.

2. Klare Regeln was wie konfiguriert wird

In vielen Fällen werden Konfigurationsformen gemischt (TX mit Annotationen, Komponenten mit XML, Web mit Annotationen). Hierbei sollte man darauf achten, das es klare und einheitliche Vorgaben gibt, was wie zu konfigurieren ist.

3. Wiederverwendbarkeit

Willst du die Klasse die zu konfigurieren ist evtl. ausserhalb des Spring Kontext in einem anderen Projekt (das evtl. ohne Spring auskommen will/muss) wiederverwenden? Dann sind Annotation eine schlechte Wahl.

4. Divide and Conquer

Das Aufteilen eines Konfigurationsfiles ist essentiell. Nur so bekommt man auch die Möglichkeit in Integrationstests nur Teile der Applikation zu laden und andere durch Mocks zu ersetzen. Beispiel wir haben ein Projekt, dass aus mehreren Subsystemen besteht. Für jedes Subsystem gibt es eine ${subsystem}-context.xml die ggf. weitere Konfigurationsfiles von Komponenten lädt. Diese sind so gestaltet, dass sie die KOnfiguration abbilden, wie sie produktiv benötigt werden (JNDI lookups, offene Referenzen zu anderen Modulen usw). Für die lokalen Tests gibt es dann zum einen eine ${subsystem}-context-dev.xml, die alle Beans, die an der Produktivumgebung klemmen durch welche ersetzt, die in der Testumgebung vorhanden sind. Klassisches Beispiel: produktiv - Datasource aus dem JNDI, test - Datasource per DriverManagerDataSource. Damit können jetzt lokal Integrationstest über das komplette System gefahren werden. Als letztes Konfigurationsartefakt gibt es eine ${subsystem}-context-mock.xml, das Mocks für alle benötigten Referenzen des Subsystems hochzieht, die sonst von anderen Subsystemen bereitgestellt werden. Dies ermöglicht es, das Subsystem in sich zu instantiieren ohne andere zu nutzen.

Lange Rede kurzer Sinn: man kann und muss Konfiguration auch über XML Files handhabbar bekommen. Wichtig ist hierbei ein sauberes Applikationsdesign, dass eine deartige Aufteilung in Subsysteme ermöglicht. Dann kann man auch die Konfigurationsdateien entsprechend modularisieren.

Ich persönlich bevorzuge in den meisten Fällen XML vor den Annotationen, einfach, weil ich mir zweimal überleg, ob ich die Abhängigkeit zu Spring im Code eingehen will. Habe ich Klassen, die eh schon von Spring abhängen (DAOs die von *DaoSupport erben) dann kann ich die auch genausogut mit Annotationen versehen.

Gruß
Ollie
 
Hallo Olliver,

vielen Dank für diese ausführliche Antwort, es ist wirklich Klasse, wie Du Dein Wissen hier mit anderen teilst (insbesondere hier gerade mit mir :). Das ist wirklich bemerkenswert (uns selten zugleich)!

Ich denke ich kann alle Punkte, die Du geschrieben hast, gut nachvollziehen und sehe alles sehr ähnlich. Autowiring gefällt mir nicht so sehr, da man sich wirklich die "Magic" wie Du es nennst, an Board holt und ich manchmal den Überblick verliere, warum was jetzt wo injiziert wird.

Noch eine kleine Anmerkung: wenn man die @Resource Annotation verwendet, kann man Referenzen injizieren (lassen) ohne Abhängigkeit zu Spring zu schaffen.

Ich werde Deine ganzen Tipps nun erstmal verdauen, und mir dann nochmal in Ruhe die richtige Strategie überlegen. Ich tendiere momentan auch dazu, den gesamten Applikationskontext eher in XML zu belassen.


Vielen Dank nochmal für Deine Hilfe!
 
Noch eine kleine Anmerkung: wenn man die @Resource Annotation verwendet, kann man Referenzen injizieren (lassen) ohne Abhängigkeit zu Spring zu schaffen.

Jap, diese zu verwenden empfiehlt Jürgen Höller auch ständig. Die meisten Springklassen, die Annotationen verarbeiten, sind so konfigurierbar, dass man sie auch auf anderen Annotationen arbeiten lassen kann. Bsp: RequiredAnnotationBeanPostProcessor.

Gruß
Ollie
 
Hallo,

also ich bin mit der Konfiguration über XML auch nicht wirklich zufrieden.
bei wirklich großen System wird das sehr schnell unübersichtlich, so dass man den Überblick
nur noch mit Hilfe von Tools bekommen kann. Auch das aufsplitten in mehrere Konfigurationsfiles macht einem hier das Leben ab einer gewissen Größe nicht mehr viel einfacher...

Ich würde mittlerweile sagen, dass man für Konfiguration und Programmlogik nur noch eine Sprache
haben sollte. Dazu muss man natürlich sagen, dass es dann für diese Sprache auch entsprechenden
Toolsupport geben muss. Weiterhin soll man Konfigurationseinstellungen in der Sprache einfach
hinschreiben können ohne irgendwas neu kompilieren zu müssen.

Konfiguration -> Interpretieren
Anwendungslogik -> Kompilieren

Das ist auch mit purem Java schon möglich. Schreibt man die Konfiguration in Java hin so kann
man diese über BeanShell interpretieren lassen. Gleichzeitg kann man, während man den
"Konfigurationscode" hinschreibt von der IDE (wie beispielsweise Eclipse) prüfen lassen und bekommt
zusätzlichen den Wunderbaren Refactoring / Toolsupport den wir alle lieben gelernt haben :)

Eine andere Möglichkeit wäre auch die Verwendung von Scala was sich auch
interpretieren und kompilieren lässt.

Gruß Tom
 
Die große Unübersichtlichkeit rührt aus der fehlenden modularisierbarkeit auf logischer Ebene. Ich kann zwar Konfigurationsdateien aufteilen, nicht aber festlegen, dass nur bestimmte Beans für andere Projekte / Schichten sichtbar sein sollen.

Abhilfe schafft hier Spring Dynamic Modules. Damit kann man indirekt die Sichtbarkeit von Services definieren in dem man nur die Beans als Services deklariert, die public zugänglich sein sollen. So wird die Komposition von neuen Services etwas übersichtlicher. Ähnliches geht auch mit Spring JavaConfig. Obwohl sich das für mich immer noch ein wenig fremd anfühlt.

Beim Toolsupport wird sich sicher auch noch einiges tun. Es gibt mit so Sachen wie den Skyway Builder (http://www.skywaysoftware.org) mittlerweile Tools, die die Springkonfiguration noch stärker abstrahieren. Allerdings stellt sich dann die Frage wie man dann damit umgeht wenn man doch mal dedizierten Zugriff auf Details benötigt.

Gruß
Ollie
 

Neue Beiträge

Zurück