Skip to content

4. Bağımlılık Enjeksiyonu

Bağımlılık enjeksiyonu, kontrol tersine çevirmenin bir sonucu olarak görülebilir. Bunu yeni bir örnekle açıklayalım. Aşağıdaki 3 katmanlı web uygulamasını ele alalım:

DAO katmanına erişimin, daha önce incelediğimiz [IArticlesDao] arayüzü tarafından kontrol edildiğini ve uygulamanın tamamının web üzerinden ürün satın almaya yönelik bir web uygulaması olduğunu varsayalım. Ürünler, [Dao] katmanı tarafından yönetilen ürünlerdir. İş katmanına erişimin aşağıdaki arayüz tarafından kontrol edildiği varsayılmaktadır:

Public Interface IArticlesDomain
     ' bir ürün sepeti satın alınır
    Sub acheter(ByVal panier As Panier)
     ' ürün listesini alıyoruz
    Function getAllArticles() As IList
     ' belirli bir ürünü alır
    Function getArticleById(ByVal idArticle As Integer) As Article
     ' hataları kaydetmek için
    ReadOnly Property erreurs() As ArrayList
End Interface

Farklı yöntemlerin anlamları üzerinde fazla durmayacağız. Sadece, satıştaki tüm ürünlerin listesini alması gereken [getAllArticles] yönteminin verilere erişmesi gerektiği belirtilmelidir. Bu verileri elde etmek için, [IArticlesDao] arayüzüne başvurması gerekir. [IArticlesDomain] arayüzünü uygulayan bir sınıfın iskeleti şu şekilde olabilir:

Imports istia.st.articles.dao
...
Namespace istia.st.articles.domain
    Public Class AchatsArticles
        Implements IArticlesDomain

         'özel alanlar
        Private _articlesDao As IArticlesDao
        Private _erreurs As ArrayList

         ' oluşturucu
        Public Sub New(ByVal articlesDao As IArticlesDao)
            _articlesDao = articlesDao
        End Sub
...
    End Class
End Namespace

Daha önce de belirttiğimiz gibi, iş katmanı arayüzünün bazı yöntemleri, [Dao] katmanından veri talep etmek zorundadır. Dolayısıyla, [IArticlesDomain] arayüzünün [AchatsArticles] uygulama sınıfımız, [IArticlesDao] arayüzünün bir uygulamasına bir referansa ihtiyaç duyar. Yukarıda, bu referans, [_articlesDao] adlı özel alandır. Bu referans, bir [AchatsArticles] nesnesinin oluşturulduğu sırada sağlanır.

[AchatsArticles] sınıfının yazıldığını ve bunu [Nunit] türünde bir testle test etmek istediğimizi varsayalım. Bu testi, bir Spring yapılandırma dosyası kullanacak şekilde oluşturalım:

...
Imports Spring.Objects.Factory.Xml
Imports System.IO
...
    <TestFixture()> _
    Public Class NunitSpringTestArticlesDomain

         ' test edilecek nesne
        Private articlesDomain As IArticlesDomain

        <SetUp()> _
        Public Sub init()
       ' Spring nesne oluşturucusunun bir örneğini alıyoruz
            Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-domain.xml", FileMode.Open))
       ' articles dao nesnesinin oluşturulmasını talep ediyoruz
            articlesDomain = CType(factory.GetObject("articlesdomain"), IArticlesDao)
        End Sub
...
    End Class

Spring'in [spring-config-domain.xml] yapılandırma dosyasının içeriği ne olabilir? Şu şekilde olabilir:

<?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>

     <!-- IArticlesDao arayüzünün uygulama sınıfı -->
    <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>

     <!-- IArticlesDomain arayüzünün uygulama sınıfı -->
  <object id="articlesdomain" type="istia.st.articles.domain.AchatsArticles, articlesdomain">
      <constructor-arg index="0">
        <ref object="articlesdao" />
    </constructor-arg>
  </object>
</objects>

Bu dosya, [Dao] katmanındaki [IArticlesDao] türündeki singleton'ı oluşturmak için halihazırda kullanılan dosyadır; buna, iş katmanındaki [IArticlesDomain] türündeki singleton'ı oluşturmak için kod eklenmiştir. Bu dosya nasıl oluşturulacaktır?

  • Harici bir kod, Spring’den yapılandırma dosyasında “articlesdomain” adlı singleton’a ilişkin bir referans ister. Test sınıfımızdaki [init] yöntemi de buna bir örnektir:
        <SetUp()> _
        Public Sub init()
       ' Spring nesne oluşturucusunun bir örneği alınır
            Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-domain.xml", FileMode.Open))
       ' articles DAO nesnesinin örneklenmesini talep ediyoruz
            articlesDomain = CType(factory.GetObject("articlesdomain"), IArticlesDao)
        End Sub
  • Spring, yapılandırma dosyasında söz konusu singleton'ın tanımını bulur. Bu singleton'ı oluşturmak için "articlesdao" adlı başka bir singleton'a ihtiyaç duyduğunu fark eder:
  <object name="articlesdomain" class="istia.st.articles.domain.AchatsArticles, articlesdomain">
      <constructor-arg index="0">
        <ref object="articlesdao" />
    </constructor-arg>
  </object>
  • Spring daha sonra "articlesdao" singletonunu oluşturacaktır. Bunun nasıl yapıldığını daha önce açıklamıştık.
  • Bu işlem tamamlandıktan sonra, "articlesdomain" singletonunu oluşturabilir ve bunu talep eden koda bir referans verebilir.

Bu mekanizma şu şekilde şematize edilebilir:

Görüldüğü gibi Spring, "articlesdomain" singletonunun "articlesdao" singletonuna olan bağımlılığını yönetmiştir. Spring'i bu şekilde kullanabilmek için, bağımlı singleton'u argüman olarak kabul eden bir yapıcıya sahip bir sınıf oluşturmamız gerekti:

Imports istia.st.articles.dao
...
Namespace istia.st.articles.domain
    Public Class AchatsArticles
        Implements IArticlesDomain

         'özel alanlar
        Private _articlesDao As IArticlesDao

         ' yapıcı
        Public Sub New(ByVal articlesDao As IArticlesDao)
            _articlesDao = articlesDao
        End Sub
...
    End Class
End Namespace

"Bağımlılık enjeksiyonu" terimi, hem:

  • bağımlılıklarına göre örneklenecek sınıfların oluşturulma şekli
  • Spring'in bu sınıfların örneklendirilmesi sırasında bu bağımlılıkları yönetme biçimi