Spring ist ein weiterverbreitetes Java-Framework und  bringt einen eigenen Mechanismus für die Dependency Injection mit sich, der mit sogenannten Beans funktioniert.

Der Begriff Dependency Injection hat seinen Ursprung in den SOLID-Principles. Dabei will die Kopplung der Klassen minimiert werden, dass heisst die Klassen sollen nicht stark von einander Abhängen und leicht ersetzbar sein. Das Dependency Injection Pattern bietet uns dafür einen guten Mechanismus um diese Kopplung zu minimieren. In einem Artikel von Martin Fowler wird der Nutzen und der Grund von Dependency Injection genauer beschreiben.

In Spring haben wir diesen Mechanismus fest verankert. Klassen die vom Spring Dependency Container verwaltet werden nennt man Beans. Diese werden durch Spring initialisiert und ihre eigenen Abhängigkeiten werden wiederum auch von Spring injectet. Für die Definition von Beans gibt es mehrere verschieden Wege, man beschreibt sie anhand von Java-Annotations oder in einer XML-Konfiguration.

Annotations-Konfiguration

Um Beans per Annotation zu konfigurieren benutzt Spring Component-Scanning. Dies bedeutet, dass Spring alle Klassen mit den Annotationen @Component, @Repository, @Service und @Controller sucht und als Bean registriert. Diese Annotationen verleihen der Klasse wiederum  einen bestimmten Nutzen im Spring Framework. So eine Klasse mit der @Controller Annotation für einen MVC-Controller.

Um Component Scanning in einem Package zu nutzen, muss es zuerst, entweder mit Annotation, oder in einer Spring-Konfiguration deklariert werden.

XML-Konfiguration

Es ist auch möglich Beans direkt im XML, in einer Spring-Konfiguration,  zu definieren. Dies bringt den Vorteil mit sich Properties einer Klasse die injected werden sollen leicht mit dem verändern einer Konfiguration zu tauschen.

Wenn das Bespiel von oben betrachtet wird, sehen wir, dass „MyTestClass“ eine Abhängigkeit auf „OtherClass“ hat, da es als Property definiert wird. Im Element „Property“ wird beschrieben mit dem Attribut „name“ wie das Property in der Klasse heist, mit „ref“ wird der Bean bestimmt welcher injected werden soll.

Wenn nun ein Property auf den Typen eines Interface gesetzt wird, ermöglich dies ganz neue Möglichkeiten, denn nun kann jede beliebige Klasse welche das Interface implementiert injectet werden. Ein Bespiel dazu:

Hier haben wir ein „CustomerRepository“ welcher einen Logger braucht um die CRUD-Operationen zu loggen. Diese werden Momentan per Email mit dem „EmailLogger“ geloggt. Der Empfänger der Emails sage, dass er zu viele Emails bekommt (quelle surprise), das Logging soll geändert werden. Die einzige Anpassung die gemacht werden muss an dem „UserRepository“ ist die „emailLogger“ Referenz auf einen anderen Logger wie Beispielsweise den „fileSystemLogger“ zu ändern. Der Code muss nicht angepasst werden, da das Interface die Methode „WriteLog“ forciert und somit müssen beide Klassen diese implementieren.

Benutzung eines Beans auf Klassenebene

Die Beans welche definiert worden sind können auf drei Weisen in einer Klasse benutzt werden.

Filed Injection

Der Nachteil hierbei ist, dass wir nicht mit Interfaces arbeiten können, da er nicht weiss welche Implementation des Interfaces er benutzen soll. Ausserdem kann die Dependency bei den Tests nicht gemockt werden. Ausserdem crashed das Programm erst in der Laufzeit falls der Bean nicht instanziiert werden konnte.  Von der Benutzung dieser Variante ist abgeraten aufgrund der vielen Nachteile. Es wird keine XML-Konfiguration benötigt.

Constructor Injection

Das ist die mockbare Alternative zur Filed Injection.  Es wird keine XML-Konfiguration benötigt.

SetterInjection

Hier kann von Interfaces Gebrauch gemacht werden.  Ausserdem ist es möglich eine XML-Konfiguration des benötigten Bean-Properties zu verlangen indem man der Setter-Methode die Annotation „Required“  setzt. Hierbei crashed der Server bereits beim Starten und zeigt den Fehler auf, was noch eine Sicherheit mehr gibt.

 

Man braucht Dependency Injection um Klassen weniger zu koppeln. Dafür stellt Spring Beans zu Verfügung, welche auf viele verschieden Weisen genutzt und deklariert werden können.