Skip to content

3. Inversion of Control (IoC)

Wenden wir uns nun dem Konzept der Inversion of Control (IoC) zu, das Spring zur Konfiguration von Anwendungen nutzt. Um dieses Konzept zu veranschaulichen, kehren wir zur Architektur unserer vorherigen Testanwendung zurück:

Um auf Daten aus dem DBMS zuzugreifen, muss die Testklasse die Dienste eines Objekts nutzen, das die Schnittstelle [IArticlesDao] implementiert, beispielsweise ein Objekt vom Typ [ArticlesDaoPlainODBC]. Wir haben zwei mögliche Lösungen für die Instanziierung eines solchen Objekts untersucht:

  • Bei der ersten Lösung forderte die Testklasse selbst die Instanziierung eines Objekts vom Typ [ArticlesDaoPlainODBC] an:
    <TestFixture()> _
    Public Class NunitTestArticlesDaoPlainOdbc

        ' the test object
        Private articlesDao As IArticlesDao

        <SetUp()> _
        Public Sub init()
            ' create an instance of the object to be tested
            articlesDao = New ArticlesDaoPlainODBC("odbc-firebird-articles", "SYSDBA", "masterkey")
        End Sub
...
    End Class

Der Code enthält eine fest codierte Abhängigkeit vom Klassennamen. Sollte sich die Klasse ändern, die die Schnittstelle [IArticlesDao] implementiert, müsste der Code in der Methode [init] angepasst werden. Zwischen den Objekten bestehen folgende Beziehungen:

Die Klasse [NunitTestArticlesDaoPlainOdbc] übernimmt die Initiative, das benötigte Objekt [ArticlesDaoPlainODBC] zu erstellen. Um auf den Begriff „Inversion of Control“ zurückzukommen, kann man sagen, dass sie diejenige ist, die die „Kontrolle“ über die Erstellung des benötigten Objekts hat.

  • Die zweite Lösung verfolgt einen anderen Ansatz. Die Testklasse sieht nun wie folgt aus:
    <TestFixture()> _
    Public Class NunitSpringTestArticlesDaoPlainOdbc

        ' the test object
        Private articlesDao As IArticlesDao

        <SetUp()> _
        Public Sub init()
      ' retrieve an instance of the Spring object manufacturer
            Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-plainodbc.xml", FileMode.Open))
      ' request instantiation of the articles dao object
            articlesDao = CType(factory.GetObject("articlesdao"), IArticlesDao)
        End Sub
    ...
    End Class

Dieser Mechanismus lässt sich wie folgt zusammenfassen:

Hier ergreift die Testklasse nicht die Initiative, um die Erstellung eines [ArticlesDaoPlainODBC]-Objekts anzufordern. Sie fragt Spring lediglich nach einer Referenz auf ein solches Objekt. Wenn das Objekt existiert, gibt Spring eine Referenz darauf zurück. Wenn es nicht existiert, erstellt Spring es. Die Testklasse hat die Kontrolle über die Erstellung des [ArticlesDaoPlainODBC]-Objekts verloren. Sie fordert lediglich eine Referenz auf dieses Objekt an. Diese Anfrage zwingt Spring in diesem Fall dazu, das Objekt zu erstellen. In einem anderen Kontext könnte man sich jedoch vorstellen, dass das angeforderte Objekt bereits auf Anfrage der Anwendung erstellt wurde. Spring erstellt das Objekt dann nicht erneut, sondern gibt eine Referenz auf das vorhandene Objekt (Singleton) zurück. Das Konzept der Inversion of Control (IoC) bedeutet hier:

  • dass die Anwendung niemals die Initiative ergreift, die benötigten Singletons zu erstellen. Sie fordert lediglich Referenzen auf diese an.
  • Es ist Spring, das entscheidet, ob bei der ersten Anforderung einer Referenz ein Singleton erstellt wird