Skip to content

5. Spring IoC uygulamalı olarak

Şimdi, daha önce gördüklerimizi örneklerle uygulamaya geçiyoruz.

5.1. Örnek 1

[Personne.vb] sınıfı şu şekildedir:

Namespace istia.st.springioc.demos
    Public Class Personne

         ' özel alanlar
        Private _nom As String
        Private _age As Integer

         ' varsayılan oluşturucu
        Public Sub New()
        End Sub

         ' özel alanlarla ilişkili özellikler
        Public Property nom() As String
            Get
                Return _nom
            End Get
            Set(ByVal Value As String)
                _nom = Value
            End Set
        End Property

        Public Property age() As Integer
            Get
                Return _age
            End Get
            Set(ByVal Value As Integer)
                _age = Value
            End Set
        End Property

         ' kimlik dizesi
        Public Overrides Function tostring() As String
            Return String.Format("[{0},{1}]", nom, age)
        End Function

         ' init yöntemi
        Public Sub init()
            Console.WriteLine("init personne {0}", Me.ToString)
        End Sub

         ' kapatma yöntemi
        Public Sub close()
            Console.WriteLine("destroy personne {0}", Me.ToString)
        End Sub

    End Class
End Namespace

Sınıf şunları içerir:

  • iki özel alan (ad ve yaş) ve bu alanlara özellikler aracılığıyla erişilebilir
  • toString nesnesinin değerini bir karakter dizesi biçiminde almak için toString yöntemi
  • nesnenin oluşturulmasında Spring tarafından çağrılacak bir init yöntemi, nesnenin yok edilmesinde çağrılacak bir close yöntemi

[Personne] türünde nesneler oluşturmak için aşağıdaki Spring [spring-config-1.xml] dosyasını kullanacağız:

<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">

<objects>
    <object id="personne1" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
        destroy-method="close">
        <property name="nom">
            <value>Simon</value>
        </property>
        <property name="age">
            <value>40</value>
        </property>
    </object>
    <object id="personne2" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
        destroy-method="close">
        <property name="nom">
            <value>Brigitte</value>
        </property>
        <property name="age">
            <value>20</value>
        </property>
    </object>
</objects>

Bu dosya

  • , [Personne] türünde sırasıyla "kişi1" ve "kişi2" adlı iki anahtar nesnesini tanımlar
  • her bir kişinin [nom, age] özelliklerini başlatır
  • [init-method] nesnesinin ilk oluşturulması sırasında ve [destroy-method] nesnesinin yok edilmesi sırasında çağrılacak yöntemleri tanımlar

Testlerimiz için NUnit test sınıflarını kullanacağız. İlki şu şekilde olacaktır:

Imports System
Imports Spring.Objects.Factory.Xml
Imports System.IO
Imports NUnit.Framework
Imports istia.st.springioc.demos

Namespace istia.st.springioc.tests

    <TestFixture()> _
    Public Class NunitTestSpringIocDemo1
         ' test edilecek nesne
        Private factory As XmlObjectFactory

        <SetUp()> _
        Public Sub init()
             ' fabrika örneği oluşturulur
            factory = New XmlObjectFactory(New FileStream("spring-config-1.xml", FileMode.Open))
             ' günlük
            Console.WriteLine("setup test")
        End Sub

        <Test()> _
        Public Sub demo()
             ' Spring dosyasındaki [Personne] nesnelerini anahtarlarına göre alınıyor
            Dim personne1 As Personne = CType(factory.GetObject("personne1"), Personne)
            Console.WriteLine("personne1=" + personne1.ToString())
            Dim personne2 As Personne = CType(factory.GetObject("personne2"), Personne)
            Console.WriteLine("personne2=" + personne2.ToString())
            personne2 = CType(factory.GetObject("personne2"), Personne)
            Console.WriteLine("personne2=" + personne2.ToString())
        End Sub

        <TearDown()> _
        Public Sub destroy()
             ' singleton'lar yok edilir
            factory.Dispose()
             ' fabrika kaynağını serbest bırakma
            factory = Nothing
             ' izleme
            Console.WriteLine("teardown test")
        End Sub

    End Class
End Namespace

Açıklamalar:

  • [spring-config-1.xml] dosyasında tanımlanan nesneleri elde etmek için [XmlObjectFactory] türünde bir nesne kullanıyoruz. Yapılandırma dosyasındaki tekil nesnelere erişim sağlayan başka "fabrika" türleri de mevcuttur. [XmlObjectFactory] nesnesi, test sınıfının [SetUp] öznitelik yönteminde elde edilir ve özel bir değişkende saklanır. <Setup()> özniteliğine sahip yöntemin her testten önce yürütüldüğünü hatırlayalım.
  • [spring-config-1.xml] dosyası, uygulamanın [bin] klasörüne yerleştirilecektir
  • Spring, çeşitli formatlardaki yapılandırma dosyalarını kullanabilir. [XmlObjectFactory] nesnesi, XML formatındaki bir yapılandırma dosyasını analiz etmeye olanak tanır.
  • Bir Spring dosyasının işlenmesi, [XmlObjectFactory] türünde bir nesne verir; burada bu nesne factory'dir. Bu nesne ile, C anahtarıyla tanımlanan bir singleton, factory.getObject(C) komutuyla elde edilir.
  • [demo] yöntemi, "personne1" ve "personne2" anahtarlarına sahip singletonların değerlerini ister ve görüntüler.

Visual Studio projesinin yapısı şu şekildedir:

Image

Açıklamalar:

  • VS projesi, [demo1] olarak adlandırılmıştır
  • [istia] klasörü kaynak kodları içerir. Derlenmiş kodlar, [bin] klasörüne yerleştirilecektir. DLL ve [demo1.dll]:

Image

  • [spring-config-1.xml] dosyası, projenin [bin] klasöründe yer almaktadır.
  • [bin] klasörü, uygulama için gerekli dosyaları içerir:
    • Spring.Core.dll, Spring.Core.xml (Spring sınıfları için)
    • log4net.dll: Spring günlükleri için
    • demo1.dll, proje oluşturma işlemi sırasında üretilen DLL dosyasıdır

Proje oluşturma işlemi sırasında üretilen DLL ve [demo1.dll] dosyaları, [Nunit-Gui 2.2] adlı grafik test aracına yüklenir. Bu araç, DLL dosyasında bulunan NUnit sınıflarını otomatik olarak görüntüler:

Image

NUnit testindeki [demo] yönteminin çalıştırılması, yukarıda belirtilen ve aşağıda tekrarlanan sonuçları verir:

***** istia.st.springioc.tests.NunitTestSpringIocDemo1.demo
setup test
init personne [Simon,40]
personne1=[Simon,40]
init personne [Brigitte,20]
personne2=[Brigitte,20]
personne2=[Brigitte,20]
destroy personne [Simon,40]
destroy personne [Brigitte,20]
teardown test

Açıklamalar:

    1. satır: Test, <Setup()> öznitelik yönteminin çalıştırılmasıyla başlar
    1. satır:
            Dim personne1 As Personne = CType(factory.GetObject("personne1"), Personne)

işlemi, [personne1] bean'inin oluşturulmasına neden oldu. [personne1] singleton tanımında [init-method="init"] yazılmış olduğu için, oluşturulan [Personne] nesnesinin [init] yöntemi çalıştırıldı. İlgili mesaj görüntülenir.

init personne [Simon,40]
    1. satır:
            Console.WriteLine("personne1=" + personne1.ToString())

işlemi, oluşturulan [Personne] nesnesinin değerini görüntüledi.

personne1=[Simon,40]
  • 5-6. satırlar: Aynı durum, [personne2] anahtar bean'i için de tekrarlanır.
init personne [Brigitte,20]
personne2=[Brigitte,20]
    1. satır: son işlem
personne2 = CType(factory.GetObject("personne2"), Personne)
Console.WriteLine("personne2=" + personne2.ToString())

sadece bir satır görüntüledi:

personne2=[Brigitte,20]

Dolayısıyla, [Personne] türünde yeni bir nesnenin oluşturulmasına neden olmamıştır. Eğer böyle olsaydı, [init] yönteminin çıktısı görüntülenirdi, ancak burada böyle bir durum söz konusu değildir. Bu, singleton ilkesidir. Spring, varsayılan olarak yapılandırma dosyasındaki bean'lerin yalnızca tek bir örneğini oluşturur. Bu, bir nesne referans hizmetidir. Henüz oluşturulmamış bir nesnenin referansı istenirse, Spring onu oluşturur ve bir referans döndürür. Nesne zaten oluşturulmuşsa, Spring sadece bir referans verir.

  • 8-10. satırlar: <TearDown()> öznitelik yöntemi çalıştırılır (10. satır). İçinde,
             ' singleton'lar yok edilir
            factory.Dispose()

işlemi, Spring tarafından oluşturulan singletonların yok edilmesine neden olur. Bu, her biri için [close] yönteminin çalıştırılmasına yol açar; çünkü yapılandırma dosyasında her biri için "destroy-method=close" yazılmıştır. Ekran çıktıları bunu göstermektedir:

destroy personne [Simon,40]
destroy personne [Brigitte,20]

Artık Spring yapılandırmasının temellerini öğrendiğimize göre, bundan sonra açıklamalarımızı biraz daha hızlı yapabileceğiz.

5.2. Örnek 2

Aşağıdaki yeni [Voiture] sınıfını ele alalım:

Imports istia.st.springioc.demos

Namespace istia.st.springioc.demos

    Public Class Voiture
         ' özel alanlar
        Private _marque As String
        Private _type As String
        Private _propriétaire As Personne

         ' genel özellikler
        Public Property marque() As String
            Get
                Return _marque
            End Get
            Set(ByVal Value As String)
                _marque = Value
            End Set
        End Property

        Public Property type() As String
            Get
                Return _type
            End Get
            Set(ByVal Value As String)
                _type = Value
            End Set
        End Property

        Public Property propriétaire() As Personne
            Get
                Return _propriétaire
            End Get
            Set(ByVal Value As Personne)
                _propriétaire = Value
            End Set
        End Property

         ' varsayılan oluşturucu
        Public Sub New()

        End Sub

         ' üç parametreli oluşturucu
        Public Sub New(ByVal marque As String, ByVal type As String, ByVal propriétaire As Personne)
             ' özel alanlar, ilişkili özellikleri aracılığıyla başlatılıyor
            With Me
                .marque = marque
                .type = type
                .propriétaire = propriétaire
            End With
        End Sub

         ' Araba nesnesinin kimlik dizesi
        Public Overrides Function tostring() As String
            Return String.Format("[{0},{1},{2}]", marque, type, propriétaire.ToString)
        End Function

         ' init-destroy yöntemleri
        Public Sub init()
            Console.WriteLine("init voiture {0}", Me.ToString)
        End Sub

        Public Sub destroy()
            Console.WriteLine("destroy voiture {0}", Me.ToString)
        End Sub

    End Class
End Namespace

Sınıf şunları içerir:

  • _type, _marque ve _propriétaire adlı üç özel alan içerir. Bu alanlar, genel özellikler aracılığıyla başlatılabilir ve okunabilir. Ayrıca, Voiture(String, String, Personne) yapıcı işlevi kullanılarak da başlatılabilirler. Sınıf ayrıca, önce başlatılmamış bir [Voiture] nesnesi oluşturulmasına ve ardından bu nesnenin genel özellikleri aracılığıyla başlatılmasına olanak tanıyan, argüman almayan bir oluşturucuya sahiptir.
  • toString nesnesinin değerini bir karakter dizesi biçiminde almak için bir toString yöntemi
  • nesnenin oluşturulmasından hemen sonra Spring tarafından çağrılacak bir init yöntemi, nesnenin yok edilmesinde çağrılacak bir destroy yöntemi

[Voiture] türünde nesneler oluşturmak için aşağıdaki Spring [spring-config-2.xml] dosyasını kullanacağız:

<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">
<objects>
     <!-- kişiler -->
    <object id="personne1" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
        destroy-method="close">
        <property name="nom">
            <value>Simon</value>
        </property>
        <property name="age">
            <value>40</value>
        </property>
    </object>
    <object id="personne2" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
        destroy-method="close">
        <property name="nom">
            <value>Brigitte</value>
        </property>
        <property name="age">
            <value>20</value>
        </property>
    </object>
     <!-- bir araba -->
    <object id="voiture1" type="istia.st.springioc.demos.Voiture, demo1" init-method="init"
        destroy-method="destroy">
        <constructor-arg index="0">
            <value>Peugeot</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>307</value>
        </constructor-arg>
        <constructor-arg index="2">
            <ref object="personne2"/>
        </constructor-arg>
    </object>
</objects>

Bu dosya, önceki tanımlara [Voiture] türünde bir "voiture1" anahtar nesnesi ekler. Bu nesneyi başlatmak için şunu yazabilirdik:

    <object id="voiture1" type="istia.st.springioc.demos.Voiture, demo1" init-method="init"
        destroy-method="destroy">
        <constructor-arg index="0">
            <value>Peugeot</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>307</value>
        </constructor-arg>
        <constructor-arg index="2">
            <ref object="personne2"/>
        </constructor-arg>
    </object>

Daha önce tanıtılan bu yöntemi seçmek yerine, burada sınıfın Voiture(String, String, Personne) oluşturucusunu kullanmayı tercih ettik. Ayrıca, [voiture1] singleton'ı, [init-method] nesnesinin ilk oluşturulmasında çağrılacak yöntemi ve [destroy-method] nesnesinin yok edilmesinde çağrılacak yöntemi tanımlar.

Testlerimiz için aşağıdaki NUnit [NunitTestSpringIocDemo2] test sınıfını kullanacağız:

Imports System
Imports Spring.Objects.Factory.Xml
Imports System.IO
Imports NUnit.Framework
Imports istia.st.springioc.demos

Namespace istia.st.springioc.tests

    <TestFixture()> _
    Public Class NunitTestSpringIocDemo2
         ' singleton fabrikası
        Private factory As XmlObjectFactory

        <SetUp()> _
        Public Sub init()
             ' fabrika örneği oluşturulur
            factory = New XmlObjectFactory(New FileStream("spring-config-2.xml", FileMode.Open))
             ' günlük
            Console.WriteLine("setup test")
        End Sub

        <TearDown()> _
    Public Sub destroy()
             ' singleton'lar yok ediliyor
            factory.Dispose()
             ' fabrika serbest bırakılıyor
            factory = Nothing
             ' izleme
            Console.WriteLine("teardown test")
        End Sub

        <Test()> _
        Public Sub demo2()
             ' singleton'ın geri alınması [voiture1]
            Dim voiture1 As Voiture = CType(factory.GetObject("voiture1"), Voiture)
            Console.WriteLine("Voiture1=[{0}]", voiture1)
        End Sub

    End Class
End Namespace

Açıklamalar:

  • <Setup()> ve <TearDown()> öznitelik yöntemleri değişmeden kalır.
  • [demo2] yöntemi, [voiture1] singletonuna bir referans alır ve bunu görüntüler.

Visual Studio projesinin yapısı eskisi gibi kalır. Yalnızca iki yeni sınıf ve bir Spring yapılandırma dosyası eklenmiştir:

Image

NUnit testinin çalıştırılması aşağıdaki sonuçları verir:

Image

Ekran görüntülerini açıklayalım:

1
2
3
4
5
6
7
8
***** istia.st.springioc.tests.NunitTestSpringIocDemo2.demo2
setup test
init personne [Brigitte,20]
init voiture [Peugeot,307,[Brigitte,20]]
Voiture1=[[Peugeot,307,[Brigitte,20]]]
destroy voiture [Peugeot,307,[Brigitte,20]]
destroy personne [Brigitte,20]
teardown test

Açıklamalar:

    1. satır: Her testten önce yürütülen [Setup] öznitelik yöntemi; burada [demo]
    1. satır: Spring, [voiture1] singletonunun oluşturulmasına başlar. Bu singleton, mevcut olmayan [personne2] singletonuna bağımlıdır. Dolayısıyla, [personne2] singletonu oluşturulur ve [init] yöntemi yürütülür.
    1. satır: [voiture1] singleton'ı artık oluşturulabilir. Ardından, [init] yöntemi yürütülür.
    1. satır: [demo2] yöntemi, [voiture1] singletonunun değerini görüntüler
  • 6-8. satırlar: Testin [TearDown] yöntemi yürütülür. Singleton'lar yok edilir, bu nedenle [destroy] yöntemleri yürütülür

5.3. Örnek 3

Aşağıdaki yeni [GroupePersonnes] sınıfını ekliyoruz:

Imports istia.st.springioc.demos

Namespace istia.st.springioc.demos

    Public Class GroupePersonnes
         ' özel alanlar
        Private _membres() As Personne
        Private _groupesDeTravail As Hashtable

         ' genel özellikler
        Public Property membres() As Personne()
            Get
                Return _membres
            End Get
            Set(ByVal Value() As Personne)
                _membres = Value
            End Set
        End Property

        Public Property groupesDeTravail() As Hashtable
            Get
                Return _groupesDeTravail
            End Get
            Set(ByVal Value As Hashtable)
                _groupesDeTravail = Value
            End Set
        End Property

         ' varsayılan oluşturucu
        Public Sub New()

        End Sub

         ' nesnenin kimlik dizesi GroupeDePersonnes
        Public Overrides Function tostring() As String
             ' grup üyeleri listesi taranıyor
            Dim identité As String = "[membres=("
            Dim i As Integer
            For i = 0 To membres.Length - 2
                identité += membres(i).ToString + ","
            Next
            identité += membres(i).ToString + "), groupes de travail=("
             ' çalışma grupları sözlüğü taranıyor
            Dim clés As IEnumerator = groupesDeTravail.Keys.GetEnumerator
            Dim clé As Object
            While clés.MoveNext
                clé = clés.Current
                identité += String.Format("[{0},{1}] ", clé, groupesDeTravail(clé))
            End While
             ' sonuç döndürülür
            Return identité + "]"
        End Function

         ' init-destroy yöntemleri
        Public Sub init()
            Console.WriteLine("init GroupeDePersonnes {0}", Me.ToString)
        End Sub

        Public Sub destroy()
            Console.WriteLine("destroy GroupeDePersonnes {0}", Me.ToString)
        End Sub

    End Class
End Namespace

Bu grubun iki özel üyesi şunlardır:

_membres: gruba üye kişilerin bulunduğu bir tablo

_groupesDeTravail: bir kişiyi bir çalışma grubuna atayan bir sözlük

Bu özel üyeler, genel özellikler aracılığıyla erişilebilir hale getirilir. Burada, Spring'in dizi veya sözlük türünde alanlara sahip nesneler gibi karmaşık nesneleri nasıl başlatabileceğini göstermeyi amaçlıyoruz.

Spring yapılandırma dosyası [spring-config-3.xml] şu şekilde olacaktır:

<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">
<objects>
     <!-- kişiler -->
    <object id="personne1" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
        destroy-method="close">
        <property name="nom">
            <value>Simon</value>
        </property>
        <property name="age">
            <value>40</value>
        </property>
    </object>
    <object id="personne2" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
        destroy-method="close">
        <property name="nom">
            <value>Brigitte</value>
        </property>
        <property name="age">
            <value>20</value>
        </property>
    </object>
     <!-- bir araba -->
    <object id="voiture1" type="istia.st.springioc.demos.Voiture, demo1" init-method="init"
        destroy-method="destroy">
        <constructor-arg index="0">
            <value>Peugeot</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>307</value>
        </constructor-arg>
        <constructor-arg index="2">
            <ref object="personne2" />
        </constructor-arg>
    </object>
     <!-- bir grup insan -->
    <object id="groupe1" type="istia.st.springioc.demos.GroupePersonnes" init-method="init"
        destroy-method="destroy">
        <property name="membres">
            <list>
                <ref object="personne1" />
                <ref object="personne2" />
            </list>
        </property>
        <property name="groupesDeTravail">
            <dictionary>
                <entry key="Brigitte">
                    <value>Marketing</value>
                </entry>
                <entry key="Simon">
                    <value>Ressources humaines</value>
                </entry>
            </dictionary>
        </property>
    </object>
</objects>
  1. <list> etiketi, tablo türü veya IList türü bir alanı farklı değerlerle başlatmaya olanak tanır.
  1. <dictionary> etiketi, IDictionary arayüzünü uygulayan bir alan için de aynı işlemi gerçekleştirmeye olanak tanır.

Testlerimiz için aşağıdaki NUnit [NunitTestSpringIocDemo3] test sınıfını kullanacağız:

Imports System
Imports Spring.Objects.Factory.Xml
Imports System.IO
Imports NUnit.Framework
Imports istia.st.springioc.demos

Namespace istia.st.springioc.tests

    <TestFixture()> _
    Public Class NunitTestSpringIocDemo3
         ' test edilecek nesne
        Private factory As XmlObjectFactory

        <SetUp()> _
        Public Sub init()
             ' fabrika örneği oluşturulur
            factory = New XmlObjectFactory(New FileStream("spring-config-3.xml", FileMode.Open))
             ' günlük
            Console.WriteLine("setup test")
        End Sub

        <TearDown()> _
        Public Sub destroy()
             ' singleton'lar yok ediliyor
            factory.Dispose()
             ' izleme
            Console.WriteLine("teardown test")
        End Sub

        <Test()> _
    Public Sub demo3()
             ' singleton'ın geri alınması [groupe1]
            Dim groupe1 As GroupePersonnes = CType(factory.GetObject("groupe1"), GroupePersonnes)
            Console.WriteLine("groupe1={0}", groupe1)
        End Sub

    End Class
End Namespace

[demo3] yöntemi, [groupe1] tekil nesnesini alır ve görüntüler.

Visual Studio projesinin yapısı eskisiyle aynı kalır; tek fark, iki ek sınıf ve bir yapılandırma dosyası eklenmiş olmasıdır.

Image

NUnit testindeki [demo3] yönteminin çalıştırılması aşağıdaki sonuçları verir:

Image

Yorumlar:

***** istia.st.springioc.tests.NunitTestSpringIocDemo3.demo3
setup test
init personne [Simon,40]
init personne [Brigitte,20]
init GroupeDePersonnes [membres=([Simon,40],[Brigitte,20]), groupes de travail=([Brigitte,Marketing] [Simon,Ressources humaines] ]
groupe1=[membres=([Simon,40],[Brigitte,20]), groupes de travail=([Brigitte,Marketing] [Simon,Ressources humaines] ]
destroy GroupeDePersonnes [membres=([Simon,40],[Brigitte,20]), groupes de travail=([Brigitte,Marketing] [Simon,Ressources humaines] ]
destroy personne [Simon,40]
destroy personne [Brigitte,20]
teardown test
  • 2. satır: Her testten önce yürütülen [Setup] öznitelik yöntemi, burada [demo]
  • satır 3-4: Spring, [groupe1] singletonunun oluşturulmasına başlar. Bu singleton, mevcut olmayan [personne1, personne2] singletonlarına bağımlıdır. Bu singletonlar oluşturulur ve [init] yöntemleri yürütülür.
  • 5. satır: [groupe1] singleton'u artık oluşturulabilir. Ardından, [init] yöntemi yürütülür.
  • 6. satır: [demo3] yöntemi, [groupe1] singletonunun değerini görüntüler
  • 7-10. satırlar: Testin [TearDown] yöntemi yürütülür. Singleton'lar yok edilir, bu nedenle [destroy]