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:

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]:

- [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:

NUnit testindeki [demo] yönteminin çalıştırılması, yukarıda belirtilen ve aşağıda tekrarlanan sonuçları verir:
Açıklamalar:
-
- satır: Test, <Setup()> öznitelik yönteminin çalıştırılmasıyla başlar
-
- satır:
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.
-
- satır:
işlemi, oluşturulan [Personne] nesnesinin değerini görüntüledi.
- 5-6. satırlar: Aynı durum, [personne2] anahtar bean'i için de tekrarlanır.
-
- satır: son işlem
personne2 = CType(factory.GetObject("personne2"), Personne)
Console.WriteLine("personne2=" + personne2.ToString())
sadece bir satır görüntüledi:
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,
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:
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:

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

Ekran görüntülerini açıklayalım:
Açıklamalar:
-
- satır: Her testten önce yürütülen [Setup] öznitelik yöntemi; burada [demo]
-
- 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.
-
- satır: [voiture1] singleton'ı artık oluşturulabilir. Ardından, [init] yöntemi yürütülür.
-
- 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>
- <list> etiketi, tablo türü veya IList türü bir alanı farklı değerlerle başlatmaya olanak tanır.
- <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.

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

Yorumlar:
- 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]