7. Bir çözüm
7.1. Visual Studio projesi
![]() | ![]() |
Açıklamalar:
- Spring için gerekli dosyalar [bin] klasörüne yerleştirilmiştir: Spring.Core.dll, log4net.dll, Spring.Core.xml
- Spring yapılandırma dosyaları [spring-config-3tier-*.xml] de [bin] klasörüne yerleştirilmiştir
- [istia] kök dizininde ise uygulamanın çeşitli sınıfları bulunmaktadır
Proje, DLL ve [spring3tier.dll] dosyalarını [bin] klasöründe oluşturacak şekilde yapılandırılmıştır:

7.2. [istia.st.spring3tier.dao] paketi
IDao arayüzü:
Namespace istia.st.spring3tier.dao
Public Interface IDao
' katmanda bir şey yapmak [dao]
Function doSomethingInDaoLayer(ByVal a As Integer, ByVal b As Integer) As Integer
End Interface
End Namespace
Birinci sınıf bir uygulama:
Namespace istia.st.spring3tier.dao
Public Class DaoImpl1
Implements istia.st.spring3tier.dao.IDao
' katmanda bir şey yapmak [dao]
Public Function doSomethingInDaoLayer(ByVal a As Integer, ByVal b As Integer) As Integer Implements IDao.doSomethingInDaoLayer
Return a + b
End Function
End Class
End Namespace
- Sınıfın özel alanı yoktur
- [doSomethingInDaoLayer] yöntemi, istenildiği gibi parametrelerinin toplamını verir.
İkinci bir uygulama sınıfı:
Namespace istia.st.spring3tier.dao
Public Class DaoImpl2
Implements istia.st.spring3tier.dao.IDao
' katmanda bir şey yapmak [dao]
Public Function doSomethingInDaoLayer(ByVal a As Integer, ByVal b As Integer) As Integer Implements IDao.doSomethingInDaoLayer
Return a - b
End Function
End Class
End Namespace
- Sınıfın özel alanı yoktur
- [doSomethingInDaoLayer] yöntemi, istenildiği gibi parametrelerinin farkını döndürür.
7.3. [istia.st.spring3tier.domain] paketi
IDomain arayüzü:
Namespace istia.st.spring3tier.domain
Public Interface IDomain
' [domain] katmanında bir şey yapmak
Function doSomethingInDomainLayer(ByVal a As Integer, ByVal b As Integer) As Integer
End Interface
End Namespace
Birinci sınıf bir uygulama örneği IDomainImpl1:
Imports istia.st.spring3tier.dao
Namespace istia.st.spring3tier.domain
Public Class DomainImpl1
Implements istia.st.spring3tier.domain.IDomain
' özel alanlar
Private _dao As IDao
' ilişkili özellik
Public WriteOnly Property dao() As IDao
Set(ByVal Value As IDao)
_dao = Value
End Set
End Property
' varsayılan oluşturucu
Public Sub New()
End Sub
' [domain] katmanında bir şey yapmak
Public Function doSomethingInDomainLayer(ByVal a As Integer, ByVal b As Integer) As Integer Implements IDomain.doSomethingInDomainLayer
a += 1
b += 1
Return _dao.doSomethingInDaoLayer(a, b)
End Function
End Class
End Namespace
- Sınıfın, [IDao] türündeki tekil nesneye bir referans olan özel bir alanı vardır; bu alan, [Dao] katmanına erişim sağlar. Bu alan, nesnenin oluşturulduğu sırada Spring tarafından (bağımlılık enjeksiyonu yoluyla) başlatılacaktır.
- [doSomethingInDomainLayer] yöntemi, parametrelerini artırır ve ardından bunları [dao] singletonunun [doSomethingInDaoLayer] yöntemine aktarır.
İkinci bir uygulama sınıfı IDomainImpl2:
Imports istia.st.spring3tier.dao
Namespace istia.st.spring3tier.domain
Public Class DomainImpl2
Implements istia.st.spring3tier.domain.IDomain
' özel alanlar
Private _dao As IDao
' ilişkili özellik
Public WriteOnly Property dao() As IDao
Set(ByVal Value As IDao)
_dao = Value
End Set
End Property
' varsayılan oluşturucu
Public Sub New()
End Sub
' [domain] katmanında bir şey yapmak
Public Function doSomethingInDomainLayer(ByVal a As Integer, ByVal b As Integer) As Integer Implements IDomain.doSomethingInDomainLayer
a -= 1
b -= 1
Return _dao.doSomethingInDaoLayer(a, b)
End Function
End Class
End Namespace
- Sınıfın, [IDao] türündeki tekil nesneye bir referans olan özel bir alanı vardır; bu alan, [Dao] katmanına erişim sağlar. Bu alan, nesnenin oluşturulduğu sırada Spring tarafından (bağımlılık enjeksiyonu yoluyla) başlatılacaktır.
- [doSomethingInDomainLayer] yöntemi, parametrelerini bir azaltır ve ardından bunları [dao] singletonunun [doSomethingInDaoLayer] yöntemine aktarır
7.4. [istia.st.spring3tier.control] paketi
IControl arayüzü:
Namespace istia.st.spring3tier.control
Public Interface IControl
' [control] katmanında bir şey yapmak
Function doSomethingInControlLayer(ByVal a As Integer, ByVal b As Integer) As Integer
End Interface
End Namespace
Birinci sınıf bir uygulama örneği ControlImpl1:
Imports istia.st.spring3tier.domain
Namespace istia.st.spring3tier.control
Public Class ControlImpl1
Implements istia.st.spring3tier.control.IControl
' özel alanlar
Private _domain As IDomain
' ilişkili özellik
Public WriteOnly Property domain() As IDomain
Set(ByVal Value As IDomain)
_domain = Value
End Set
End Property
' varsayılan oluşturucu
Public Sub New()
End Sub
' [control] katmanında bir şey yapmak
Public Function doSomethingInControlLayer(ByVal a As Integer, ByVal b As Integer) As Integer Implements IControl.doSomethingInControlLayer
a += 1
b += 1
Return _domain.doSomethingInDomainLayer(a, b)
End Function
End Class
End Namespace
- Sınıfın, [IDomain] türündeki tekil nesneye bir referans olan özel bir alanı vardır; bu alan, [Domain] katmanına erişim sağlar. Bu alan, nesnenin oluşturulduğu sırada Spring tarafından (bağımlılık enjeksiyonu yoluyla) başlatılacaktır.
- [doSomethingInControlLayer] yöntemi, parametrelerini artırır ve ardından bunları [domain] singletonunun [doSomethingInDomainLayer] yöntemine aktarır.
İkinci bir uygulama sınıfı IControlImpl2:
Imports istia.st.spring3tier.domain
Namespace istia.st.spring3tier.control
Public Class ControlImpl2
Implements istia.st.spring3tier.control.IControl
' özel alanlar
Private _domain As IDomain
' ilişkili özellik
Public WriteOnly Property domain() As IDomain
Set(ByVal Value As IDomain)
_domain = Value
End Set
End Property
' varsayılan oluşturucu
Public Sub New()
End Sub
' [control] katmanında bir şey yapmak
Public Function doSomethingInControlLayer(ByVal a As Integer, ByVal b As Integer) As Integer Implements IControl.doSomethingInControlLayer
a -= 1
b -= 1
Return _domain.doSomethingInDomainLayer(a, b)
End Function
End Class
End Namespace
- Sınıfın, [IDomain] türündeki tekil nesneye bir referans olan özel bir alanı vardır; bu alan, [Domain] katmanına erişim sağlar. Bu alan, nesnenin oluşturulduğu sırada Spring tarafından (bağımlılık enjeksiyonu yoluyla) başlatılacaktır.
- [doSomethingInControlLayer] yöntemi, parametrelerini azaltır ve ardından bunları [domain] singletonunun [doSomethingInDomainLayer] yöntemine aktarır.
7.5. [Spring] yapılandırma dosyaları
[spring-config-3tier-1.xml] dosyası, aşağıdaki uygulamaların 1. sürümlerini kullanı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>
<!-- DAO sınıfı -->
<object id="dao" type="istia.st.spring3tier.dao.DaoImpl1, spring3tier"></object>
<!-- domain sınıfı -->
<object id="domain" type="istia.st.spring3tier.domain.DomainImpl1, spring3tier">
<property name="dao">
<ref object="dao" />
</property>
</object>
<!-- kontrol sınıfı -->
<object id="control" type="istia.st.spring3tier.control.ControlImpl1, spring3tier">
<property name="domain">
<ref object="domain" />
</property>
</object>
</objects>
[spring-config-3tier-2.xml] dosyası, aşağıdaki uygulamaların 2. sürümlerini kullanı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>
<!-- DAO sınıfı -->
<object id="dao" type="istia.st.spring3tier.dao.DaoImpl2, spring3tier"></object>
<!-- domain sınıfı -->
<object id="domain" type="istia.st.spring3tier.domain.DomainImpl2, spring3tier">
<property name="dao">
<ref object="dao" />
</property>
</object>
<!-- kontrol sınıfı -->
<object id="control" type="istia.st.spring3tier.control.ControlImpl2, spring3tier">
<property name="domain">
<ref object="domain" />
</property>
</object>
</objects>
7.6. [istia.st.spring3tier.tests] test paketi
Bir Nunit testi [NunitTestSpring3tier.vb]:
Imports System
Imports Spring.Objects.Factory.Xml
Imports System.IO
Imports NUnit.Framework
Imports istia.st.spring3tier.control
Imports istia.st.spring3tier.domain
Namespace istia.st.springioc.tests
<TestFixture()> _
Public Class NunitTestSpring3tier
' singleton fabrikaları
Private factory1 As XmlObjectFactory
Private factory2 As XmlObjectFactory
<SetUp()> _
Public Sub init()
' singleton fabrikaları oluşturulur
factory1 = New XmlObjectFactory(New FileStream("spring-config-3tier-1.xml", FileMode.Open))
factory2 = New XmlObjectFactory(New FileStream("spring-config-3tier-2.xml", FileMode.Open))
End Sub
<TearDown()> _
Public Sub destroy()
' singleton'ları yok ediyoruz
factory1.Dispose()
factory2.Dispose()
' singleton fabrikalarını serbest bırakma
factory1 = Nothing
factory2 = Nothing
End Sub
<Test()> _
Public Sub test()
'arayüzün bir uygulamasını alıyoruz IControl
Dim control1 As IControl = CType(factory1.GetObject("control"), IControl)
' sınıfı kullanıyoruz
Dim a1 As Integer = 10, b1 As Integer = 20
Dim res1 As Integer = control1.doSomethingInControlLayer(a1, b1)
Assert.AreEqual(34, res1)
' IControl arayüzünün başka bir uygulamasını alıyoruz
Dim control2 As IControl = CType(factory2.GetObject("control"), IControl)
' sınıfı kullanıyoruz
Dim a2 As Integer = 10, b2 As Integer = 20
Dim res2 As Integer = control2.doSomethingInControlLayer(a2, b2)
Assert.AreEqual(-10, res2)
End Sub
End Class
End Namespace
Bu testin gerçekleştirilmesi sonucunda aşağıdaki sonuçlar elde edilir:

Bu belgenin renkli sürümüne sahip okuyucular, sonuçların "yeşil" olduğunu ve bunun testin başarılı olduğunu gösterdiğini göreceklerdir.
7.7. Başka bir Spring yapılandırma dosyası türü
Bir VB.net uygulaması, [App.config] adlı bir dosya kullanılarak yapılandırılabilir. Bu dosya, Visual Studio projesinin kök dizinine yerleştirilir:

Spring bu yapılandırma dosyasından yararlanabilir. [Spring.net] belgelerindeki örneklerden esinlenerek hazırlanan aşağıdaki [App.config] dosyasını ele alalım:
<?xml version="1.0" encoding="iso-8859-1" ?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
<resource uri="config://spring/objects" />
</context>
<objects>
<!-- ilk yapılandırma -->
<!-- dao sınıfı -->
<object id="dao1" type="istia.st.spring3tier.dao.DaoImpl1, spring3tier"></object>
<!-- domain sınıfı -->
<object id="domain1" type="istia.st.spring3tier.domain.DomainImpl1, spring3tier">
<property name="dao">
<ref object="dao1" />
</property>
</object>
<!-- control sınıfı -->
<object id="control1" type="istia.st.spring3tier.control.ControlImpl1, spring3tier">
<property name="domain">
<ref object="domain1" />
</property>
</object>
<!-- ikinci bir yapılandırma -->
<!-- DAO sınıfı -->
<object id="dao2" type="istia.st.spring3tier.dao.DaoImpl2, spring3tier"></object>
<!-- domain sınıfı -->
<object id="domain2" type="istia.st.spring3tier.domain.DomainImpl2, spring3tier">
<property name="dao">
<ref object="dao2" />
</property>
</object>
<!-- kontrol sınıfı -->
<object id="control2" type="istia.st.spring3tier.control.ControlImpl2, spring3tier">
<property name="domain">
<ref object="domain2" />
</property>
</object>
</objects>
</spring>
</configuration>
Not: Aşağıdaki bilgiler kesin değildir. Yukarıdaki yapılandırma dosyasındaki tüm öğelerin anlamını doğru bir şekilde anladığımdan emin değilim.
XML dosyasının [App.config] sözdizimi, şu sözdizimine uymasını gerektirir:
[App.config] dosyasının farklı bölümlerinin yönetimi harici programlara devredilebilir. [ConfigSections] bölümünde de bu şekilde yapılmıştır:
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
Yukarıdaki kod, [spring/context] adlı bölümün, [Spring.Context.Support.ContextHandler] sınıfı tarafından yönetilmesi gerektiğini belirtir; bu sınıf[Spring.Core.dll] montajında bulunur ve [spring/objects] adlı bölümün, yine [Spring.Core.dll] montajında bulunan [Spring.Context.Support.DefaultSectionHandler] sınıfı tarafından yönetilmesi gerektiğini ifade eder.
[spring/context] bölümü şu şekildedir:
<spring>
<context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
<resource uri="config://spring/objects" />
</context>
...
</spring>
Burada, yapılandırma dosyasının [spring/objects] bölümü, [Spring.Core.dll] derlemesinde bulunan [Spring.Context.Support.XmlApplicationHandler] sınıfı tarafından yönetilmesi gerektiği belirtiliyor gibi görünüyor. Bu sınıf, konumu [ config://spring/objects], c.a.d olan XML kaynağını kullanmalıdır. mevcut yapılandırma dosyasının [spring/objects] bölümü.
[spring/objects] bölümünde, artık alıştığımız Spring sözdizimini görüyoruz.
[App.config] dosyasının <objects>... </objects> bölümünde, 3 katmanlı uygulamamız için iki olası yapılandırma tanımladık:
- biri, arayüz uygulamalarının 1. sürümünü kullanıyor
- diğeri ise aynı arayüzlerin 2. sürümünü kullanan yapılandırma
Peki, [App.config] dosyasını nasıl kullanabiliriz?
Aşağıdaki kod, önceki [App.config] dosyasını kullanan bir konsol uygulamasını göstermektedir:
Imports System
Imports Spring.Context
Imports System.IO
Imports NUnit.Framework
Imports istia.st.spring3tier.control
Imports istia.st.spring3tier.domain
Imports System.Configuration
Namespace istia.st.springioc.tests
Module MainTestSpring3tier
Public Sub main()
' singletonları almamızı sağlayacak Spring bağlamı
Dim contexte As IApplicationContext = CType(ConfigurationSettings.GetConfig("spring/context"), IApplicationContext)
' IControl arayüzünün ilk bir uygulamasını alıyoruz
Dim control1 As IControl = CType(contexte.GetObject("control1"), IControl)
' sınıfı kullanıyoruz
Dim a1 As Integer = 10, b1 As Integer = 20
Console.WriteLine("res1({0},{1})={2}", a1, b1, control1.doSomethingInControlLayer(a1, b1))
' IControl arayüzünün başka bir uygulamasını alıyoruz
Dim control2 As IControl = CType(contexte.GetObject("control2"), IControl)
' sınıfı kullanılır
Dim a2 As Integer = 10, b2 As Integer = 20
Console.WriteLine("res2({0},{1})={2}", a2, b2, control2.doSomethingInControlLayer(a2, b2))
' duraklama
Console.WriteLine("Tapez [entrée] pour continuer...")
Console.ReadLine()
End Sub
End Module
End Namespace
Açıklamalar:
- Şimdiye kadar kullandığımız NUnit örneklerinde, ihtiyacımız olan tekil nesneleri elde etmek için [XmlObjectFactory] nesnesini kullanıyorduk. Burada kullanılan nesne, bir Spring arayüzü olan [IApplicationContext] türündedir. Bu nesne, [App.config]'ten, geleneksel olarak .NET'te yapılandırma dosyalarını işlemek için kullanılan [ConfigurationSettings] sınıfı aracılığıyla elde edilir.
- [spring/context] bölümünün yöneticisi istenir. [App.config] dosyasına bakıldığında, bu dosyanın [XmlApplicationContext] türünde olduğu ve [App.config] dosyasının [spring/objects] bölümünü yönetmekle görevli olduğu görülür.
- [IApplicationContext] türündeki nesne alındıktan sonra, bu nesne şimdiye kadar kullandığımız [XmlObjectFactory] nesnesi gibi kullanılır.
Önceki programın adı [MainTestSpring3tier.vb]'tir ve [tests] paketinde yer almaktadır:

[spring3tier] projesi, [MainTestSpring3tier] için şu şekilde yapılandırılmıştır:

Projenin çalıştırılması aşağıdaki sonuçları verir:
7.8. Conclusion
Spring çerçevesi, hem uygulama mimarisinde hem de yapılandırmalarında gerçek bir esneklik sağlar. Spring'in iki temel unsurundan biri olan IoC kavramını kullandık. Diğer temel unsur ise, burada ele almadığımız AOP (Aspect Oriented Programming) kavramıdır. Bu kavram, sınıf kodunu değiştirmeden yapılandırma yoluyla bir sınıf yöntemine "davranış" eklemeye olanak tanır. Basitçe ifade etmek gerekirse, AOP belirli yöntemlere yapılan çağrıları filtrelemeye olanak tanır:
![]() |
- Filtre, hedef M yönteminden önce, sonra veya her ikisinde de çalıştırılabilir.
- M yöntemi bu filtrelerin varlığından haberdar değildir. Bu filtreler Spring yapılandırma dosyasında tanımlanır.
- M yönteminin kodu değiştirilmez. Filtreler, oluşturulacak Java sınıflarıdır. Spring, özellikle SGBD işlemlerini yönetmek için önceden tanımlanmış filtreler sağlar.
- Filtreler, bean'lerdir ve bu nedenle Spring yapılandırma dosyasında bean'ler olarak tanımlanırlar.
Yaygın olarak kullanılan bir filtre, işlem filtresidir. İş katmanındaki, veriler üzerinde birbirinden ayrılamaz iki işlem (iş birimi) gerçekleştiren bir M yöntemini ele alalım. Bu yöntem, bu iki işlemi gerçekleştirmek için DAO katmanındaki M1 ve M2 adlı iki yöntemi çağırır.
![]() |
İş katmanında yer aldığı için M yöntemi, bu verilerin depolandığı ortamı göz ardı eder. Örneğin, verilerin bir SGBD'te olduğunu varsaymak zorunda değildir ve M1 ile M2 yöntemlerine yapılan iki çağrıyı bir SGBD işlemi içine yerleştirmesi gerekmez. Bu ayrıntılarla ilgilenmek DAO katmanının görevidir. Bu soruna bir çözüm olarak, DAO katmanında, M1 ve M2 yöntemlerini kendisi çağıran bir yöntem oluşturulabilir; ve bu çağrıları SGBD işlemine dahil etmesi.
![]() |
AOP filtreleme çözümü daha esnektir. Bu çözüm, M çağrısından önce bir işlem başlatacak ve çağrıdan sonra duruma göre bir commit veya rollback gerçekleştirecek bir filtre tanımlamaya olanak tanır.
![]() |
Bu yaklaşımın birçok avantajı vardır:
- filtre bir kez tanımlandıktan sonra, örneğin işlem gerektiren tüm yöntemler gibi birden fazla yönteme uygulanabilir
- bu şekilde filtrelenen yöntemlerin yeniden yazılmasına gerek kalmaz
- kullanılacak filtreler yapılandırma yoluyla tanımlandığından, bunlar değiştirilebilir
Daha fazla bilgi için: http://www.springframework.net.





