4. Dependency Injection
Die Dependency Injection kann als Folge der Inversion of Control betrachtet werden. Wir werden dies anhand eines neuen Beispiels veranschaulichen. Betrachten Sie die folgende 3-Tier-Webanwendung:
![]() |
Wir gehen davon aus, dass der Zugriff auf die DAO-Schicht durch die zuvor besprochene Schnittstelle [IArticlesDao] gesteuert wird und dass es sich bei der gesamten Anwendung um eine webbasierte Shopping-Anwendung handelt. Die Artikel werden von der [Dao]-Schicht verwaltet. Wir nehmen an, dass der Zugriff auf die Geschäftsschicht durch die folgende Schnittstelle gesteuert wird:
Public Interface IArticlesDomain
Public Interface IArticlesDomain
' buy a basket of items
Sub acheter(ByVal panier As Panier)
' get the list of articles
Function getAllArticles() As IList
' get a specific item
Function getArticleById(ByVal idArticle As Integer) As Article
' to record errors
ReadOnly Property erreurs() As ArrayList
End Interface
Wir werden nicht näher auf die Bedeutung der verschiedenen Methoden eingehen. Wir möchten lediglich anmerken, dass die Methode [getAllArticles], die die Liste aller zum Verkauf stehenden Artikel abrufen soll, Zugriff auf die Daten benötigt. Um diese zu erhalten, muss sie die Schnittstelle [IArticlesDao] aufrufen. Das Grundgerüst einer Klasse, die die Schnittstelle [IArticlesDomain] implementiert, könnte wie folgt aussehen:
Imports istia.st.articles.dao
...
Namespace istia.st.articles.domain
Public Class AchatsArticles
Implements IArticlesDomain
'private fields
Private _articlesDao As IArticlesDao
Private _erreurs As ArrayList
' manufacturer
Public Sub New(ByVal articlesDao As IArticlesDao)
_articlesDao = articlesDao
End Sub
...
End Class
End Namespace
Wie bereits erwähnt, müssen bestimmte Methoden der Business-Layer-Schnittstelle Daten von der [Dao]-Schicht anfordern. Unsere Implementierungsklasse [AchatsArticles] der Schnittstelle [IArticlesDomain] benötigt daher eine Referenz auf eine Implementierung der Schnittstelle [IArticlesDao]. Oben dient das private Feld [_articlesDao] als diese Referenz. Diese Referenz wird bereitgestellt, wenn ein [AchatsArticles]-Objekt instanziiert wird.
Angenommen, die Klasse [ItemPurchases] wurde geschrieben und wir möchten sie mit einem [Nunit]-Test testen. Erstellen wir diesen Test so, dass er eine Spring-Konfigurationsdatei verwendet:
...
Imports Spring.Objects.Factory.Xml
Imports System.IO
...
<TestFixture()> _
Public Class NunitSpringTestArticlesDomain
' the test object
Private articlesDomain As IArticlesDomain
<SetUp()> _
Public Sub init()
' retrieve an instance of the Spring object manufacturer
Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-domain.xml", FileMode.Open))
' request instantiation of the articles dao object
articlesDomain = CType(factory.GetObject("articlesdomain"), IArticlesDao)
End Sub
...
End Class
Wie würde der Inhalt der Spring-Konfigurationsdatei [spring-config-domain.xml] aussehen? Er könnte wie folgt lauten:
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">
<objects>
<description>Gestion d'une table d'articles</description>
<!-- the IArticlesDao interface implementation class -->
<object id="articlesdao" type="istia.st.articles.dao.ArticlesDaoPlainODBC, articlesdao">
<constructor-arg index="0">
<value>odbc-firebird-articles</value>
</constructor-arg>
<constructor-arg index="1">
<value>SYSDBA</value>
</constructor-arg>
<constructor-arg index="2">
<value>masterkey</value>
</constructor-arg>
</object>
<!-- the IArticlesDomain interface implementation class -->
<object id="articlesdomain" type="istia.st.articles.domain.AchatsArticles, articlesdomain">
<constructor-arg index="0">
<ref object="articlesdao" />
</constructor-arg>
</object>
</objects>
Diese Datei ist diejenige, die bereits zur Instanziierung des [IArticlesDao]-Singletons aus der [Dao]-Schicht verwendet wurde, zu der wir den Code zur Instanziierung des [IArticlesDomain]-Singletons aus der Geschäftsschicht hinzugefügt haben. Wie wird dies aufgebaut?
- Externer Code fordert in der Konfigurationsdatei eine Referenz auf das Singleton namens „articlesdomain“ von Spring an. Dies ist bei der [init]-Methode unserer Testklasse der Fall:
<SetUp()> _
Public Sub init()
' retrieve an instance of the Spring object manufacturer
Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-domain.xml", FileMode.Open))
' request instantiation of the articles dao object
articlesDomain = CType(factory.GetObject("articlesdomain"), IArticlesDao)
End Sub
- Spring findet die Definition des betreffenden Singletons in seiner Konfigurationsdatei. Es stellt fest, dass es zur Instanziierung ein weiteres Singleton namens „articlesdao“ benötigt:
<object name="articlesdomain" class="istia.st.articles.domain.AchatsArticles, articlesdomain">
<constructor-arg index="0">
<ref object="articlesdao" />
</constructor-arg>
</object>
- Spring instanziiert dann das Singleton „articlesdao“. Wie dies geschieht, haben wir bereits erläutert.
- Sobald dies geschehen ist, kann es das „articlesdomain“-Singleton instanziieren und eine Referenz darauf an den Code zurückgeben, der es angefordert hat.
Dieser Mechanismus lässt sich wie folgt schematisch darstellen:
![]() |
Wir sehen, dass Spring die Abhängigkeit des „articlesdomain“-Singletons vom „articlesdao“-Singleton verwaltet hat. Um Spring auf diese Weise zu nutzen, mussten wir eine Klasse mit einem Konstruktor erstellen, der das abhängige Singleton als Argument akzeptiert:
Imports istia.st.articles.dao
...
Namespace istia.st.articles.domain
Public Class AchatsArticles
Implements IArticlesDomain
'private fields
Private _articlesDao As IArticlesDao
' manufacturer
Public Sub New(ByVal articlesDao As IArticlesDao)
_articlesDao = articlesDao
End Sub
...
End Class
End Namespace
Der Begriff „Dependency Injection“ umfasst beides:
- die spezifische Art und Weise, wie die zu instanziierenden Klassen auf der Grundlage ihrer Abhängigkeiten aufgebaut werden
- die Art und Weise, wie Spring diese Abhängigkeiten bei der Instanziierung dieser Klassen verwaltet

