m i.c o
ww w. ja
va
dil
java/j2ee Uygulama Çatısı & Spring AOP
Orçun DAYIBAŞ
(
[email protected])
2004, Ankara
m i.c o
İçindekiler
ww w. ja
va
dil
1. Giriş ................................................................................................................................... 2 1.1. Spring J2EE Uygulama Çatısı Nedir?................................................................... 2 1.2. Spring Nasıl Çalışır?................................................................................................ 6 1.2.1. Denetim Çevirimi (Inversion of Control) .................................................... 7 1.2.2. Geliştirim Yaklaşımı........................................................................................ 9 1.2.3. BeanFactory ve Çekirdek Sınıfı...................................................................... 9 1.2.4. Çekirdeğin Yaşam Döngüsü ......................................................................... 10 1.2.5. Merhaba Spring! ............................................................................................ 11 1.3. Kullanım Seneryoları ............................................................................................ 12 2. Spring AOP ile Uygulama Geliştirimi ......................................................................... 13 2.1. Uygulama Örneği................................................................................................... 13 2.1.1. Yöntem İzleme İlgisinin Uygulanması ....................................................... 16 2.1.2. İlgilerin Yeniden Kullanımı.......................................................................... 19 3. Sonuç ............................................................................................................................... 23 4. Terimler Sözlüğü............................................................................................................ 24 5. Kaynaklar........................................................................................................................ 25
1
1.1.
m
1. Giriş
Spring J2EE Uygulama Çatısı Nedir?
va
dil
i.c o
Spring, J2EE (Java 2 Enterprise Edition) uygulamalarını geliştirme süreçlerini kolaylaştırmayı amaçlayan bir uygulama geliştirme çatısıdır (application framework). Spring oldukça kullanışlı bir çok özelliği bünyesinde barındırır. Bu özellikler, çatıyı oluşturan yedi farklı birim tarafından içerilir.
ww w. ja
Şekil 1.1. Spring uygulama çatısının alt yapı bileşenleri
Bağımlılık iletimini (bkz. Bölüm 1.2.1) sağlayan kabuk birimi, uygulama çatısının en temel birimidir. Bu birim, geliştiriciye çekirdek kozasının işlevlerini yönetme olanağı verir. Kabuğun içerdiği temel kavram olan “BeanFactory”, çekirdek yaratımında tekilliğin sağlanması gerekliliğini ortadan kaldırıp, bağımlılıkların biçim ve tanımlarını eşlemeyi programlama mantığından dışlar. Kabuk biriminin üstünde, çekirdeklere uygulama çatısı tarzında erişimi sağlayan, bağlam birimi bulunur. Bağlam birimi, özelliklerini çekirdek biriminden kalıtır. Bu özelliklere metin tabanlı ileti gönderme desteği gibi özellikleri de ekler. DAO birimi, çaba gerektiren JDBC kodlama ve veri tabanı üreticisine bağımlı hata kodlarını ortadan kaldıran JDBC soyutlama katmanını sağlar. JDBC paketi, sadece özel ara yüzleri gerçekleştiren sınıflara değil, tüm POJO’lara (Plain Old Java Objects / Basit Java Nesneleri) da birim işlem yönetimi gerçekleştirmek üzere programlama ve tanımlama yöntemleri sunar. ORM birimi, JDO, iBatis ve Hibernate de dahil olmak üzere, popüler nesne-ilişkisel eşleme API’lerine (Application Programming Interface / Uygulama Programlama 2
m
Arayüzü) bütünleştirme katmanı sunar. Geliştirici, ORM birimini kullanarak, tüm bu nesne-ilişkisel eşleyicileri Spring’in diğer tüm imkanlarıyla birlikte kullanabilir.
i.c o
Spring’in AOP birimi, yönelim tabanlı programlama gerçekleştirimi olan AOP politikası sunar. Bu politika sayesinde, geliştirici kodunda bağımlılık yaratacak eşlemelerden uzak, işlevsel tanımlamalar yapabilir. Kod düzeyi ara-veri (meta-data) işleviyle, tüm davranışsal veriler koda dahil edilebilir. (.NET platformundaki nitelikler gibi)
ww w. ja
va
dil
Spring’in Web birimi, servlet dinleyicileri ve web tabanlı uygulama bağlamını kullanarak bağlamlara ilk değer atama gibi temel web tabanlı bütünleşim özelliklerini sağlar. Ayrıca bu birim, Spring’in WebWork ya da Struts ile birlikte kullanıldığı durumlarda bütünleşimi de gerçekleştirir.
Şekil 1.2. Spring ara katmanının üçüncü parti bir web çatısı ile kullanımı
Spring’in Web MVC (Model-View-Control / Model-Görünüm-Denetim) birimi, web uygulamaları için Model-Görünüm-Denetim gerçekleştirimini sağlar. Spring’in MVC gerçekleştirimi, yalnızca basit bir gerçekleştirim değil, Spring çatısının tüm özelliklerine (örneğin; geçerlilik denetimi) taban olan, model ile etki alanı arasında kesin ayrımı sağlar. Spring, bir koza (container), bileşenleri biçimlendirmek ve bir araya getirmek için bir çatı ve birim işlem iletimi, kalıcı saklama işlemi gibi bir dizi servisten oluşur. Spring çatısını kullanarak bir uygulama oluşturulurken, aşağıdaki adımlar gerçekleşir:
3
Kozaya yerleştirilecek, alt düzey Java çekirdekleri kodlanır. Birbirine bağımlı çekirdeklerle ilgili kontroller kodlanmadan Spring çatısının kontrolüne bırakılır.
•
Çekirdekler düzenlenir. Bu aşamada, çoğunlukla Spring’in XML düzenleme servisi kullanılarak, çekirdeklerin isimleri, sınıfları, veri alanları ve varsa ilk değer atamaları tanımlanır.
•
Spring, XML kütüklerini okuyup elde ettiği ilk değer atamaları ve tanımları kullanır ve Java çekirdekleri yaratılır.
i.c o
m
•
dil
Spring’in ana birimi, bağımsız çekirdekleri ve tanımları bir araya getirerek uygulamayı çalışır hale getiren XML çekirdek fabrikasıdır. Alternatif olarak, Spring otomatik bağlantı özelliğini kullanarak tanım bilgisine ihtiyaç duymaksızın bir çook bağlantı yapabilir. Örneğin, eğer uygulama tek bir veri kaynağına ihtiyaç duyuyor ve geliştirici sadece bu veri kaynağını tanımlamış ise Spring bu veri kaynağına otomatik bağlantı yoluyla erişebilir. Yukarıda anlatılan tanım ve yaratım servis alt yapısının üstünde bazı servisler yer alır. Bunların bir çoğu basit, üst düzey soyutlama sağlayan servislerdir. İlgili servisler, J2EE mimarisinde yer alan servislerin yada diğer alt düzey uygulama çatılarından yararlanırlar. Aşağıda, Spring desteklediği çatılar özetlenmiştir: JDBC kalıcı saklama çatısı: Bu çatı, basit JDBC uygulamalarının geliştirilmesini kolaylaştırır. SQLState ile, SQLE’nin sunduğundan daha anlamlı bir hiyerarşiye sahip aykırı durum kümesi sunar. En önemlisi, JDBC’nin detaylarına boğulmadan bütünleşik ve tutarlı kodlama olanakları sunar.
•
OR eşleme çatısı: Bu çatı, Hibernate ve JDO gibi OR araçlarını Spring’in içerisinde kullanmayı olanaklı kılar.
ww w. ja
va
•
•
Birim işlem çatısı: Spring’deki bildiri temelli birim işlemler sayesinde, oldukça fazla kodlama yerine, sadece birim işlem politikası tanımlanarak gerçekleştirim kolaylaştırılır.
•
MVC Web çatısı: Strust’da olduğu gibi, Spring de model, görünüm ve denetimi bu çatıyı kullanarak, birbirinden kesin olarak ayırır.
Spring’i kullanmak için yukarıdaki çatıların ayrıntılarını bilmeye gerek yoktur. EJB’den farklı olarak, geliştirici yukarıdaki çatıları kademeli ve ihtiyaçları doğrultusunda, uygulamasına ekleyebilir.
Spring’in gerçekleştirimi sırasında, geliştiriciler, var olan denenmiş (güvenilir) çatıları kullanarak Spring’in içine yerleştirmişlerdir. Bu yaklaşım sayesinde servisler arası soyutlama sağlanmış ve göreli küçük bir servis kümesini kullanarak uygulama geliştirmek daha kolay bir hale gelmiştir. Spring, giderek daha fazla rağbet gören hafif koza (lightweight container) yaklaşımını benimsemiştir. Bu yaklaşımın ağır koza’dan (heavyweight container) farkları aşağıdaki gibi özetlenebilir: 4
Ağır koza, ön tanımlı tür bileşenlerini kabul eder. Örneğin; EJB bileşenleri, doğrudan bir kaç taban sınıftan kalıtılır. Microsoft’un OLE ortamı, standart bir arayüzün gerçekleştirimini zorunlu kılar. Tomcat sunucuları sadece servlet’leri kabul eder. Diğer taraftan hafif kozalar Java nesnelerini tanımlamak için, yansıma (reflection) yada yaratım yöntemlerini (constructor) kabul ederler.
•
Ağır kozalar, üzerlerine yerleştirilecek bileşenlere daha fazla bağımlılık koşarlar. EJB kozaları, EJB yaşam döngüsünü gerçekleştirmek üzere esnek olmayan bir API kullanmak zorundadırlar. EJB bileşenleri kalıtım, işlem dizileri gibi gerçekleştirimler için sıkı tanımlara sahiptirler. Bazı durumlarda bu tanımların tekrarlanmasını gerektiren durumlar olabilir. Spring, bileşenlere her hangi bir bağımlılık koşmaz. Böylece, Spring bileşenleri koza dışında da kolaylıkla çalıştırılıp sınanabilir çok daha az bir çaba bile farklı mimarilere uygun hale getirilebilir.
i.c o
m
•
ww w. ja
va
dil
İlk bakışta bile yaklaşımlar arasındaki oldukça büyüktür. Her iki yaklaşımı da kullanan bir geliştirici, aradaki farkın sadece can sıkıcı detaylardan kurtulmaktan çok daha fazlası olduğunu görecektir.
5
Spring Nasıl Çalışır?
m
1.2.
i.c o
Spring uygulama çatısının temel çalışma mantığı, çekirdeklerin bağımlılık iletimi tasarım örüntüsü’ne göre ele alınmasıdır. (bkz. Bölüm 1.2.1) Çekirdekler, kendilerine bağımlı sınıflardaki verilere sahiplerdir. Çekirdekler, kendi niteliklerini ve bağımlılığı bulunan diğer çekirdekleri, çekirdek tanımlayıcı kütüklerdeki verileri kullanarak tanımlarlar.
va
dil
Çekirdek, sözü edilen sınıfların olgularının yaratmak ya da JNDI istemlerini kullanarak sınıfların yerini saptamak zorunda değildir. Spring uygulama çatısı, tanımlayıcıyı kullanarak ilgili sınıfların yerini belirleme işini üstlenir ve bu sınıfları istemci sınıf için erişilebilir kılar.
ww w. ja
Şekil 1.3. Uygulama katmanları ve ele aldıkları yapılandırma kütükleri
Spring bağımlılık iletimi (bkz. Bölüm 1.2.1) tasarım örüntüsünde Assembler (Bütünleştirici) rolünü üstlenir. Denetimin, bütünleştiriciye geçmesi ile bağımlı sınıflar üzerinde değişikler yapılandırma kütüğündeki basit bir değşiklikle yapılabilir hale gelir. Bu örüntü özelliğinin Spring’e yansıması olarak; Spring, bağlaşımı indirgeyerek, sistemi birim sınamalar için de uygun hale getirmiş olur. Bu durum Spring’in neden bağımlılık iletimi tasarım örüntüsünü kullandığını açıklar.1 Spring’in sağladığı diğer özelliklerden bir kaçı aşağıdaki gibi özetlenebilir: •
Spring, BeanFactory (bkz. Bölüm 1.2.3.) yardımı ile kendiliğinden, hangi çekirdeklerin bağımlı olduğuna karar verebilir.
•
Spring, çekirdek üzerindeki bağımlılıkları denetleyebilir. Kurulması zorunlu olan değerleri, ilklendirme sırasında denetleyebilir. Denetimin yapılmaması
1
Martin Fowler’ın “Bağımlılık İletimi” örüntüsü ile yerine uygulanabilecek, “Servis Yerleştiricisi” tasarım örüntüsünü bir örnek ile karşılaştırdığı yazısına ulaşmak için; URL: http://www.martinfowler.com/articles/injection.html#ServiceLocatorVsDependencyInjection
6
•
m
durumunda, BeanFactory, varsayılan değeri kurar. Bu özellik zorunlu değil seçimseldir. (istenildiğine devreden çıkarılabilir) Spring, birden fazla kaynak kütüğünü aynı anda yönetebilir.
i.c o
1.2.1. Denetim Çevirimi (Inversion of Control)
2004 yılı başlarında Martin Fowler, kişisel sitesinde denetim çevrimi hakkında okuyucularına şunu sordu: “denetimin hangi yönü çevrilir ?”. Denetim çevrimi hakkındaki karşılıklı tartışmalardan sonra M. Fowler, örüntünün isminin değiştirilmesini önerdi. İçeriğini daha çok belli eden yeni isim; Bağımlılık İletimi (Dependency Injection) olarak M.Fowler tarafından kullanılmaya başlandı.2
dil
Çağdaş geliştiriciler, denetim sahipliğini değiştirerek uygulamalarına etkili yararlar sağlarlar. Çoğu uygulamada, nesneler yada bileşenlerle servisler arasında kalıcı bağlar kurulur. Geliştirici bu yaklaşımı uygular ise, bu yaklaşımın tüm olumsuz yönlerini de koduna dahil etmiş olur. Bazı durumlarda servislerin doğrudan çağrılması gerekebilir.
va
Geliştirici, servisi çağıran ve servis arasındaki bağımlılığı kaldırmak isteyebilir. Pasif Alan Modeller’inde (Passive Domain Models) olduğu gibi denetim sahipliğinin değiştirilebildiği bir mimari ile uygulama daha güçlü ve esnek bir yapı kazanabilir. Bu kazancın basitçe denetimi uygulamadan çatıya geçirerek elde edebildiğimizi söyleyebiliriz. Tanımladığımız bu yaklaşıma denetim çevirimi (inversion of control) denir.
ww w. ja
Denetim Çevrimi (ya da diğer adı ile Bağımlılık İletimi), nesnenin gerçekleştirimini ve bağımlı olduğu nesnelerin yaratımından ayırır. Gerçekleştirim ile yaratım arası ilişkilerin sorumluluğu Bütünleştirici (Assembler) kod kesimine bırakılır. Gerçekleştirimine ihtiyaç duyulan nesneye, bağımlı olduğu nesnelerin yaratımını ihtiyaç duymadan erişilebilir. Bütünleştirici ihtiyaç duyarsa bu nesneleri yaratabilir. Bütünleştirici bu düzenlemeyi yaparken yanlızca yapılandırma kütüğünü (Configuration File) kullanır. Böylece, Spring çok etkin ve kolay sınama imakanları sağlar. Bağımlılık İletiminin (Denetim Çevrimi / D.Ç.) üç türü vardır:
•
1. Tür D.Ç. : Arayüz iletimi (Interface Injection) olarak da bilinir. Arayüz kullanarak iletim gerçekleştirilir. Arayüz, iletim yöntemlerini tanımlar ve gerçekleştirim sınıfı bu arayüzü kullanır.
•
2. Tür D.Ç. : Kurucu iletimi (Setter Injection) olarak da bilinir. İletim kurucu yöntem aracılığı ile gerçekleştirilir. Kurucu yöntem, gerekli olduğunda bağımlı sınıfları edinmek için kullanılır.
2
Martin Fowler’ın Denetim Çevrimi/Bağımlılık İletimi hakkındaki yazısı konu hakkında detaylı bilgi içerir. Yazıya yazıya ulaşmak için; URL: http://martinfowler.com/articles/injection.html
7
3. Tür D.Ç. : Yapıcı iletimi (Constructor Injection) olarak da bilinir. İlgili sınıf, tüm bağımlılıklarının edinilmesi için bir yapıcı tanımlar. Bağımlı sınıflar yapıcı yöntemin işleneni olarak geçirilirler.
m
•
va
dil
i.c o
Spring uygulama çatısı, yukarıdaki türlerden Kurucu ve Yapıcı iletimlerini destekler (2. ve 3. tür D.Ç.’ler). Önerilen, Kurucu iletimi kullanmaktır.
ww w. ja
Şekil 1.4. Hafif Denetim Çevirimi Kozaları
Hafif kozalarda, denetim çevirimi, uygulamanın belirli bir yönüne odaklanır; bileşenlerin bağımlılık iletimi (dependency injection) doğrultusunda düzenlenmesi ve uygulamanın bir bütün haline getirilmesi. Bileşenler ile servisler arası kalıcı bağlantıların yerini düzenleme tanımları alır ve uygulamanın bir bütün haline getirilmesi uygulama geliştirme çatısının denetimine bırakılır. Nesnelerin yaratımı ve niteliklerinin ilgili değerlere kurulması gibi işlemler, geleneksel uygulamalardan, hafif kozaların oluşturduğu çatılara aktarılmıştır. Bu aktarım sürecinde, koza iki farklı bağımlılığı karşılar: veri kaynağının biçimine bağımlılığı ve DAO (Data Access Object)’nun veri kaynağına bağımlılığı. Bu yaklaşımla, bağlaşım (Coupling) koddan biçim tanımlarına kayar ve Tekil kalıp (Singleton) yapıları kaybolur. Geliştirici, basitçe sınıf ve biçim tanımlarını yapar, uygulama çatısı nesnelerin olgularını yaratıp, uygulamayı oluşturur.
8
m
1.2.2. Geliştirim Yaklaşımı
i.c o
Spring uygulama çatısının temel paketi, org.springframework.beans paketidir. Spring uygulama çatısı, JavaBeans’i kullanır ve bu paket Java çekirdekleri üzerinde yapılacak olan işlemlerin, temel imkanlarını çoğunu sağlar. Aynı zamanda, JavaBeans, Spring’in içerdiği diğer bazı sınıflara da alt yapı sağlar. Spring’in her şeyi demek olan Bağımlılık İletimi tasarım örüntüsü de temelini bu pakete dayandırır. Kullanıcı, Spring uygulama çatısının olanaklarından iki farklı yolu kullanarak yararlanabilir: • •
BeanFactory ApplicationContext
dil
BeanFactory, Spring çekirdeklerinin verilerini tutan ve kullanıcının bu verileri yönetmesini sağlayan üreysel bir üretim birimidir (generic factory). BeanFactory ile kullanıcı, Spring uygulama çatısının temel olanaklarını kolaylıkla kullanabilir.
va
ApplicationContext, BeanFactory’nin üstüne konumlanarak, Spring uygulama çatısının sağladığı tüm temel olanakları kalıtır. Bu temel olanaklara ek olarak, ApplicationContext, Olay Yönetimi (Event Managment), Uluslararasılaştırma (Internationalization) ve Kaynak Yönetimi (Resource Managment) gibi olanakları da kullanıcıya sunar.
ww w. ja
BeanFactory, özellikle düşük bellek kullanımı gerektiren durumlarda (Örneğin; tüm API’yi içeren bir applet kaynak sıkıntısı yaratabilir.) yararlıdır. Spring’in temel özelliklerini kullanılabilir kılar ve ApplicationContext’in içerdiği fazladan özellikleri uygulamaya dahil etmez.
ApplicaitonContext, Spring’i uygulama çatısı tabanlı bir uygulama geliştirimi için kullanırken, BeanFactory, programsal bir yaklaşım sunar.
1.2.3. BeanFactory ve Çekirdek Sınıfı
BeanFactory, bir grup çekirdek içeren bir üretim birimi sınıfı gibidir. BeanFactory, ilgili çekirdeklerin BeanDefinition (çekirdek tanım belirtimi) verilerini tutarak, kullanıcıdan istek gelmesi durumunda ,bu çekirdeklerden her hangi birinin bir olgusunu oluşturabilir.
XMLBeanFactory, Spring uygulama çatısı tarafından sağlanan bir BeanFactory gerçekleştirimidir. XMLBeanFactory, BeanDefinition verilerini doğrudan XML kütüğünden okuyabilir. Bu işlem sırasında XMLBeanFactory, “beans.dtd” adlı DTD kütüğünü kullanır. Böylece kütükten erişilen verinin geçerlilik denetimini gerçekleştirmiş olur.
9
i.c o
m
BeanFactory içinde tanımlı çekirdek, uygulamadaki iş mantığını içeren çekirdektir. Spring uygulama çatısı, çekirdek yapıları için her hangi bir yapıyı kullanıcıya zorlamaz (Bu konuda bir standart koşmaz). J2EE uyumlu her çekirdek yapısı, Spring tarafından da kabul edilir. Strust ya da diğer başka uygulama çatılarındakinden farklı olarak, çekirdeklere her hangi bir Spring arayüzü uygulanmadan, çekirdekler çatı içerisinde kullanılabilir durumdadır. Kullanılacak olan denetim çevrimi türüne bağlı olarak, çekirdek ilgili tasarım örüntüsü kurallarını gözetebilir. Örneğin; yapıcı iletimi kullanacak bir çekirdek, yapıcı yöntemleri tanımlamalıdır. Spring uygulama çatısı, yalnızca kurucu ve yapıcı iletimlerini destekler. Fakat, önerilen, birden fazla yapıcı yöntem çekirdeği hantallaştırıp yönetimi zorlaştıracağından, kurucu iletimi kullanmaktır.
dil
Bir çekirdeğe ilişkin bir ya da daha fazla kimlik olabilir. BeanFactory kimlik verisini kullarak ilgili çekirdeğe ulaşağından, kimlik verisi, BeanFactory içerisinde biricik olmalıdır. Çekirdeğin birdan fazla kimliğe sahip olması durumunda, bu kimlikler arma (alias) olarak tanımlanır.
va
Spring uygulama çatısı, çekirdeklerin nasıl yaratılacağıyla ilgilenip, istemciye ilgili veriyi geri döner. Çekirdekler tekil kalıp olarak tanımlanabilir. Bu durumda, ilgili çekirdek koza içerisinde belirli bir anda yalnızca bir olgu ile var olabilir. BeanFactory’ye gelen istemlere bu tek çekirdek kullanılarak cevap verilir. Tekil kalıp olarak tanımlanmamış ya da ön ürün (Prototype) olarak tanımlanmış çekirdekler, birden fazla olguya sahip olabilirler. Bu durumda, BeanFactory’e gelen her istemde yeni bir olgu yaratılır ve bu olgu kullanılarak istemciye cevap verilir.
ww w. ja
BeanFactory, her yeni istemde (her istemci için) yeni bir olgu yaratıldığından, ön ürün olarak tanımlı çekirdekler için yaşam döngüsü yönetimi (Lifecycle Managment) yapamaz. Bir sonraki bölüm, çekirdeklerin yaşam döngüsünü ele alır.
1.2.4.Çekirdeğin Yaşam Döngüsü
Çekirdek yaratıldıktan ve ilk değer atama işlemleri gerçekleştirildikten sonra, BeanFactory, geri çağırım yöntemlerini (callback methods) kullanarak, BeanFactory içindeki çekirdeğin davranışlarına müdahale edebilir. Bu yöntemlerden biri ilk-yöntem’dir (init-method). InitializingBean arayüzü, BeanFactory içinde çekirdek özellikleri kurulduktan sonra ilklendirme (Initialization) yeteneği sağlar. InitializingBean içerisindeki afterPropertiesSet() yöntemi, kullanıcıya tüm çekirdek özelliklerinin doğru kurulup kurulmadığını denetleme olanağı sağlar. Kullanıcı bu yöntem aracılığı ile, özelliklerin kurulmasının hemen ardından ele alınması gereken işlemleri de yerine getirebilir. Bu yöntemi kullanacak bir çekirdek, InitializingBean arayüzünü gerçekleştirir ve gerek duyduğu işlemleri afterPropertiesSet() yöntemi içerisinde içerir. Eğer ilklendirme işlem yükü düşük düzeyde ise, kullanıcı çekirdek içerisinde tanımladığı bir yöntem ile bu işlemleri ele alabilir. Bur durumda, gerçekleştirilen yöntem
10
m
çekirdeğin ilk-yöntem niteliğinin karşılığı olarak tanımlanır (init-method attribute). Bu yaklaşımın benimsenmesi halinde, çekirdeğin, InitializingBean arayüzünü gerçekleştirme zorunluluğu kalkar.
1.2.5. Merhaba Spring!
i.c o
Yukarıda çekirdeğin ilklendirme işlemlerinden bahsettik. Aynı yaklaşım ile, çekirdeğin kullanımı için tanımlı DisposableBean arayüzü de çekirdek yok edildikten sonra ele alınması gereken işlemleri sağlar. İlkelendirmede olduğu gibi, sonlandırmada da gerçekleştirilen yöntem, çekirdeğin son-yöntem niteliğinin karşılığı olarak tanımlanır (destroy-method attribute).
dil
Aşağıda basit bir çekirdeği tanımlayan XML kod parçası verilmiştir.
ww w. ja
va
<property name="benimString"> Merhaba Spring! Uygulamasi <property name="bagimliSinifKimlik"> <property name="bagimliString"> Merhaba Spring! Uygulamasinin bana ihtiyaci var.
Kod 1.1. İlk yapılandırma kütüğü
Yukarıdaki örnek, MerhabaSpring sınıfının tanımını gösterir. Bu sınıf, IlkSinif sınıfına bağımlıdır. benimString özelliği varsayılan değeri ile birlikte tanımlanmıştır. BeanFactory, tanımlanan çekirdeğin birinciBağımlıSinif’a ihtiyaç duyduğunu bildiğinden, bu sınıfın bir olgusunu ana sınıfın başvuru (reference) verisini kurmadan önce yaratır.
ozellikleriKutuktenAl() yöntemi ilk-yöntem olarak tanımlandığından, IlkSinif’ın özellikleri kurulduktan hemen sonra çağrılır.
11
Kullanım Seneryoları
m
1.3.
ww w. ja
va
dil
i.c o
Bölüm 1.1.’de açıklanan uygulama çatısını oluşturan birimler sayesinde, Spring basit bir applet’den karmaşık dağıtık bir uygulamaya kadar her alanda kullanılabilir.
Şekil 1.3. Örnek Spring Web Uygulaması
Yukarıdaki gösterilen mantıksal çizim tipik bir Spring web uygulamasını gösterir. Bu uygulama Spring’in sağladığı olanakların büyük bir kısmını içinde barındırır. TransactionProxyFactoryBeans kullanılarak, web uygulaması EJB’nin sağladığı koza denetimli birim işlemler gibi tamamen birim işlemsel bir yapı kazanabilir. Tüm iş mantığı (business logic), Spring’in bağımlılık iletimi (dependency injection) kozası tarafından yönetilen basit java nesneleri (POJO’lar) kullanılarak gerçekleştirilebilir. Web katmanından bağımsız E-posta gönderimi, veri geçerlilik denetimi gibi ilave servisler, geliştiriciye geçerlilik kurallarını istediği noktada uygulamaya dahil etme olanağı sağlar. Spring’in ORM desteği, Hibernate, JDO ve iBatis ile bütünleşiktir. Örneğin; HibernateDaoSupport kullanarak, geliştirici var olan Hibernate eşlemelerini tekrar kullanabilir. Form Denetimleri, alan modeli aracılığı ile web katmanıyla bütünleşir. Böylelikle, ActionForms ya da HTTP değiştirgelerini uygulamanın alan modelindeki değerler ile değiştiren bir başka sınıfa gerek kalmaz. Bu sınıflar koda dahil edilmez.
12
m
2. Spring AOP ile Uygulama Geliştirimi
i.c o
Spring, AOP3 çerçevesinde neler sunar?
"Amaç tam anlamıyla bir AOP gerçekleştirimini sağlamak yerine, (her ne kadar Spring AOP bunu fazlasıyla karşılasa da) J2EE uygulamalarında karşılaşılan genel problemlerin çözümüne yardımcı olmak için, AOP gerçekleştirimi ile Spring'in denetim çevrimi yaklaşımı arasında bir tümleştirme sağlamaktır" Spring Başvuru Belgesi
dil
Yukarıda Spring geliştirme ekibi tarafından tanımlanan hedefe ulaşmak için, Spring uygulama çerçevesi AOP kavramlarının bir kısmına (seçilmiş bir alt kümesine) destek verir. Bu bölümde aşağıdaki AOP kavramlarının Spring içerisinde nasıl gerçekleştirildiği ele alınacaktır: Tavsiyeler (Advices): before/afterReturning ve afterThrowing tavsiyeler çekirdek olarak nasıl tanımlanır?
•
Kesim Noktaları (Pointcuts): XML Spring Çekirdek Yapılandırma kütüğünün içeriğini bir araya getirmek üzere bir eylemsiz kesim noktası mantığı nasıl tanımlanır?
•
Danışmanlar (Advisors): Pointcut tanımlamaları ile Advice çekirdeklerini ilişkilendirme nasıl gerçekleştirilir?
ww w. ja
va
•
2.1.
Uygulama Örneği
“Genellikle, Spring katı kurallar koyan bir yapıya sahip değildir. Farklı alıştırmalar yapmayı kolaylaştırırken, kullanıcıya bir yaklaşımı zorlamaktan kaçınır." Spring Başvuru Belgesi
Spring çatısının AOP yeteneklerini sınamak için, öncelikle basit bir java uygulaması oluşturmalıyız. Spring uygulama çatısı içerisinde, IBusinessLogic arayüzü ve BusinessLogic sınıfı, çekirdek için basit oluşturum parçaları sağlarlar. Her ne kadar bizim basit uygulamamızın mantığı içerisinde ilgili arayüz gerekli olmasa da, bu gerçekleştirim yaklaşımı da iyi bir alılştırma olacaktır.
3
AOP hakkında daha ayrıntılı bilgi için: http://www.aosd.net
13
dil
i.c o
m
<property name="proxyInterfaces"> AisMantigi <property name="target">
Kod 2.1. springyapilandirma.xml
va
Spring’in çalışma zamanı yapılandırması, çekirdeğe hangi işlemlerin ve birimlerin uygulanacağına karar verebilir. Bu yapılandırma bilgisi, springyapilandirma.xml yapılandırma kütüğü tarafından sağlanır.
ww w. ja
Yapılandırma bilgisi, yüklenecek çekirdeğin AIsMantigi arayüzünü gerçekleştirmesi gerektiğini belirtir. Ardından, çekirdek gerçekleştirim sınıfı olarak IsMantigi ile ilişkilendirilir. Bu kadar basit bir yöntem çağrımı için bu kadar fazla tanımlama yapmak oldukça fazla gibi gözükse de, aslında gerçekleştirilen bütünün bu ufak parçası Spring bileşenlerinin uygulamamıza uygulanmasını sağlar.
public interface AIsMantigi { public void yontem(); }
Kod 2.2. AIsMantigi.java
public class IsMantigi implements AIsMantigi { public void yontem() { System.out.println("IsMantigi.yontem()'in icinde!"); } }
Kod 2.3. IsMantigi.java
14
IsMantigi çekirdeğinin "public" yöntemlerini çağırmak için, bir AnaUygulama
m
sınıfı tanımlayabiliriz.
i.c o
import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; public class AnaUygulama { public static void main(String [] args) { // Yapilandirma Kutugunu Oku ApplicationContext ctx = new FileSystemXmlApplicationContext ("springyapilandirma.xml");
dil
// Nesnenin Olgusunu Yarat AIsMantigi sinamaNesnesi = (AIsMantigi) ctx.getBean("isMantigiCekirdegi");
}
}
va
// Cekirdegin "public" yontemini cagir (sinama) sinamaNesnesi.yontem();
Kod 2.4. AnaUygulama.java
AnaUygulama, ctx.getBean(“isMantigiCekirdegi”)çağrısı ile çekirdeğin bir
ww w. ja
olgusunun oluşturulması ve Spring uygulama çatısına yüklenmesinin yönetimini gerçekleştirir. Spring’in IsMantigi çekirdeğini ilklendirmeyi denetlemesine izin vermek, Spring’in çekirdek uygulamaya sunulmadan çalışma zamanında tüm J2EE dizgesini yönetmesini sağlar. Aşağıdaki çizge, AnaUygulama her hangi bir açı uygulanmadan çalıştırıldığında oluşacak ardıl işlem çizgesini (Sequence Diagram) gösterir:
Çizge 2.1. AnaUygulama için ardıl işlem çizgesi
15
m
2.1.1. Yöntem İzleme İlgisinin Uygulanması
i.c o
İlgiye Yönelik Programlama yaklaşımının içerdiği en temel özelliklerden biri, yöntem izleme ilgisidir (Method Tracing Aspect). Bu eylemsiz ilgi, uygulama kolaylığı açısından da İlgiye Yönelik Programlama gerçekleştirimine iyi bir başlangıç noktasıdır. Yöntem izleme ilgisi, yöntemleri çağıran ve yöntmelerden dönen bağlamları ele alarak, hedef uygulama içerisindeki izlenen yöntem hakkında bilgi edinmeye olanak tanır. İlgiye yönelik yaklaşımdaki sonra ve önce tavsiye (Advice) türleri, yöntem çağırımından önce ya da sonra tetiklenebildiklerinden, bu tür katılım noktalarını (join point) elde etmek için kullanılır. Spring uygulama çatısını kullanarak, önce türü tavsiye gerçekleştirimi,
dil
IzlemeOnceTavsiye sınıfında örneklenmiştir.
import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice;
ww w. ja
va
public class IzlemeOnceTavsiye implements MethodBeforeAdvice { public void before(Method yontem, Object[] args, Object hedef) throws Throwable { System.out.println( "Merhaba Spring! (" + this.getClass().getName() + ")"); } } Kod 2.5. IzlemeOnceTavsiye.java
Benzer yaklaşımla, sonra türü tavsiye IzlemeSonraTavsiye sınıfı ile örneklenmiştir: import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class IzlemeSonraTavsiye implements AfterReturningAdvice { public void afterReturning(Object nesne, Method yontem, Object[] args, Object hedef) throws Throwable { 16
}
i.c o
}
m
System.out.println( "Merhaba Spring! (" + this.getClass().getName() + ")");
Kod 2.6. IzlemeSonraTavsiye.java
Her iki sınıf da Spring uygulama çatısının ilgili arayüzünü gerçekleştirerek, tavsiyenin belirli bir parçasını oluşturmuştur. Her iki tür tavsiyede de before(..) ya da afterReturning(..) yöntemleri, Spring’in çalışma zamanında uygun katılım noktasına ulaşıldığında, tavsiyeyi uyarmasını sağlamak için tanımlanmış yöntemlerdir.
dil
Tanımlanan tavsiyelerin uygulamanın uygun katılım noktaları ile ilişkilendirilmesi için, springyapilandirma.xml yapılandırma kütüğünde ilgili günlemelerin yapılması gerekir.
va
ww w. ja
<property name="proxyInterfaces"> AIsMantigi <property name="target"> <property name="interceptorNames"> <list> IzlemeOnceTavsiye IzlemeSonraTavsiye
17
m
i.c o
<property name="advice"> <property name="pattern"> .*
dil
<property name="advice"> <property name="pattern"> .*
va
Kod 2.7. springyapilandirma.xml
ww w. ja
Önceki yapılandırma kütüğüne yeni tanımladığımız iki tavsiye (IzlemeSonraTavsiye, IzlemeOnceTavsiye) eklendi. Her bir tavsiye, ilişkilendirildiği çekirdekteki katılım noktalarını kesiştirir. Tanımlanan bu tavsiyeler de kendi başlarına birer çekirdek olarak yapılandırma kütüğünde tanımlanır. Bu çekirdeklerin tek işlevi, kesim noktalarını bir araya getirmek ve ilişkilendirildikleri çekirdeğe tavsiye etmektir. Bu örnek için kesim noktaları, katılım noktalarını belirten düzgün deyimlerdir (regular expressions). org.springframework.aop.support.RegexpMethodPointcutAdvisor kesim noktası tavsiye kaynağı bu örnek için kullanıldığından, kesim noktası mantığı düzgün deyimler kullanılarak tanımlanmıştır. AIsMantigi arayüzündeki farklı toplamalarda (Collections) kullanılabilecek düzgün değimler hakkında aşağıdaki basit örnekler verilebilir:
•
.* : Bu deyim çekirdekteki tüm katılım noktalarını seçer.
•
./AIsMantigi/.yontem : Bu deyim, sadece AIsMantigi icinde tanimli yontem () yöntemini seçer.
Bu haliyle, yapılandırma kütüğü izleme ilgisi için uygun hale gelmiştir. AnaUygulama’nın bir dahaki işletilişinde, IsMantigi sınıfı içerisinde tanımlı tüm yöntemler izlenecektir. Bu durum aşağıdaki ardıl işlem çizgesinde gösterilmiştir:
18
m i.c o
dil
Çizge 2.2. AnaUygulama için ardıl işlem çizgesi (açısal yaklaşım ile)
2.1.2. İlgilerin Yeniden Kullanımı
va
Yöntem izleme ilgisi, biraz daha karmaşık bir yapı kazandırılarak, günlük (Logging) ilgisi olarak genişletilebilir. Günlük ilgisi için gerekli çoğu özellik önceki ilgi olan yöntem izlemede gerçekleştirildiğinden, bu ilgi yeniden kullanım için iyi bir örnek sağlar.
ww w. ja
Bu örnek için; günlük ilgisi, yöntem izleme ilgisini uygulama işletilirken oluşan aykırı durumlar gibi ek bilgileri görüntüleme amacı ile genişletir. Günlük ilgisinin etkin olarak kullanılması için, uygulamada bazı değişiklikler yapılmalıdır. public class IsMantigiAykiriDurumu extends Exception { // Aykiri Durum Tanimi }
Kod 2.8. IsMantigiAykiriDurumu.java
public interface AIsMantigi { public void yontem(); public void aykiriYontem() throws IsMantigiAykiriDurumu; }
Kod 2.9. AIsMantigi.java
19
i.c o
m
public class IsMantigi implements AISMantigi { public void yontem() { System.out.println("IsMantigi.yontem()'in icinde!"); } public void aykiriYontem() throws IsMantigiAykiriDurumu { System.out.println("IsMantigi.aykiriYontem()'in icinde!"); throw new IsMantigiAykiriDurumu(); } }
dil
Kod 2.10. IsMantigi.java
Artık, AnaUygulama içerisinde, void aykiriYontem() yöntemine bir çağrı var. Buna ek olarak, olası aykırı durum oluşumlarına karşı bir hata yakalama kod parçası da eklenmiştir.
ww w. ja
va
import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; public class AnaUygulama { public static void main(String [] args) { // Yapilandirma Kutugunu Oku ApplicationContext ctx = new FileSystemXmlApplicationContext("springyapilandirma.xml"); // Nesnenin olgusunu yarat AIsMantigi sinamaNesnesi = (AIsMantigi) ctx.getBean("ismantigicekirdegi");
// Cekirdegin "public" yontemlerini islet sinamaNesnesi.yontem(); try { sinamaNesnesi.aykiriYontem(); } catch(IsMantigiAykiriDurumu imad) { System.out.println("IsMantigiAykiriDurumu yakalandi!"); }
}
}
Kod 2.11. AnaUygulama.java
20
m
Yöntem izleme ilgisinin IzlemeOnceTavsiye ve IzlemeSonraTavsiye tavsiyeleri tamamen yeniden kullanılabilir durumdadır. GunlukAykiriTavsiye sınıfı, yeni aykırı durum günlükleme işlemi için bir tavsiye sağlar.
dil
i.c o
import org.springframework.aop.ThrowsAdvice; import java.lang.reflect.Method; public class GunlukAykiriTavsiye implements ThrowsAdvice { public void afterThrowing(Method yontem, Object[] args, Object hedef, Throwable altsinif) { System.out.println("Gunluk girdisi: " + altsinif + "aykiri durumu olustu."); } }
Kod 2.12. GunlukAykiriTavsiye.java
ww w. ja
va
Günlük ilgisinin uygulamaya eklenmesi için son adım olarak yapılandırma kütüğüne, (springyapilandirma.xml) bu ilgi (GunlukAykiriTavsiye) ile ilgili tanımların eklenmesi gerekir.
<property name="advice"> <property name="pattern"> .*
Kod 2.13.Günlük ilgisi için, springyapilandirma.xml kütüğüne eklenecek kod parçaları
21
va
dil
i.c o
m
Çizge 2.3 AnaUygulama işletilerek, günlükleme ilgisinin Spring uygulama çatısı tarafından ele alındığında oluşacak akışı gösteren UML ardıl işlem çizgesini gösterir.
ww w. ja
Çizge 2.3. AnaUygulama için ardıl işlem çizgesi (Günlük tavsiyesi eklendikten sonra)
Bu örnek ile ele alınan günlük ilgisi, Spring uygulama çatısını kullanarak, var olan ilgilerin yeniden nasıl kullanılacağını, throws biçimli tavsiyelerin nasıl kullanılacağını gösterir. Daha karmaşık ve detaylı bir günlükleme yapısı, (Ör: LOG4J 4) önce ve sonra türü yeni tavsiyeler tanımlayarak hali hazırda var olan yöntem izleme ilgisinin gerçekleştirimini geçersiz kılarak (override) elde edilebilir.
4
LOG4J hakkında daha ayrıntılı bilgi için, http://logging.apache.org/log4j/docs/
22
m
3. Sonuç
i.c o
Spring uygulama çatısı, çok yeni bir çatı olmasına rağman kısa sürede yazılım geliştirme dünyasında oldukça ses getirmiştir. Bu durumun başlıca nedeni; Spring’in var olan çözümleri (Ör: Hibernate, JDO, AOP,... gibi) kopyalamayıp, bu çözümleri bir uyum içerisinde bir araya getirmesinde yatar (Ancak, Spring geliştiricileri Strust’un yeterince sağlam olduğundan şüphe ettiklerinden, yeni bir Internet çatısı tanımlamışlardır).
dil
Spring, uygulama sunucusundan ve ortamdan bağımsız bir yapıya sahiptir. Böylece, uygulama sunucuları arası taşınabilirdir (Websphere, Weblogic, Jboss gibi yaygın uygulama sunucuları ile uyumludur). Spring geliştirim ekibinin amaçları doğrultusunda, Spring geliştiricinin yazması gereken kod yükünü azaltır. Spring uygulama çatısının bir diğer artısı, uygulama geliştirme ekibindeki tüm geliştiricilerin Spring’i bilmesini gerektirmemesidir. Spring uygulama gerçekleştirimleri için, Eclipse düzleminde destek bir eklenti yolu ile sağlanabilmektedir5. İlerliyen zamanlarda daha fazla sayıda IDE’nin Spring’i desteklemesi ile gerçekleştirim süreci daha da kısalacaktır. Spring’e başlangıç noktası olarak, Spring geliştirme ekibi tarafından tanımlanan (bu belge hazırlanırken, hala geliştiriliyordu) Spring Başvuru Belgesi (bkz. Bölüm 5.) yeterli bir belgedir. Bu bağlamda, Spring’in tek eksi yanı – şu an için – hakkında detaylı fazla bir belge bulunmamasıdır (Bu açık şu an ileti listesi6 ile kapatılıyor).
va
AOP (Aspect Oriented Programming / İlgiye Yönelik Programlama) yeni ve oldukça hızlı kabul gören bir programlama yaklaşımıdır. Spring bu yaklaşımı Spring AOP aracılığı ile içerir. Spring AOP, AOP gerçekleştirimleri için oldukça yeterli olmakla birlikte gerekli görüldüğünde AspectJ 7 de Spring uygulama çatısı ile kullanılabilir.
ww w. ja
Spring uygulama çatısının J2EE düzlemindeki başarısından sonra, Spring geliştiricileri uygulama çatılarını .NET düzlemine uyarladılar.8 Bu durumun Spring’in gelişimine olumlu bir etkisi olacağı tartışılmaz. Spring uygulama çatısı içerdiği özellikler ve özgün yaklaşımları ile yazılım geliştirme dünyasında daha uzun süre tercih edilecek gibi görünüyor. Bu belgenin hazırlanması sırasında görüşlerini aldığım, Sn. Turgay ÇELİK9, Sn. Oğuz ASLANTÜRK10 ve Sn. Bedir TEKİNERDOĞAN11’a katkılarından dolayı teşekkür ederim. Orçun DAYIBAŞ
5
Eclipse Spring UI hakkında detaylı bilgi için : http://www.springframework.org/spring-ide/eclipse/ Spring uygulama çatısı ileti listesi : http://sourceforge.net/mailarchive/forum.php?forum_id=30287 7 AspectJ Java için AOP desteği sağlar, ayrıntılı bilgi : http://eclipse.org/aspectj/ 8 .NET düzlemi için Spring uygulama çatısı: http://www.springframework.net 9 Hacettepe Üniversitesi / Araş. Gör. 10 Hacettepe Üniversitesi / Öğr. Gör. 11 Twente Üniversitesi / Doç. Dr. 6
23
İngilizce
Türkçe
i.c o
Arma İlgiye Yönelik Programlama Bütünleştirici Çekirdek İş Mantığı Toplama Yapılandırma Kütüğü Koza Bağlaşım Bağımlılık İletimi Tasarım Örüntüleri Üretim Birimi Kütük Çatı Üreysel İlklendirme Arayüz İletimi Denetim Çevrimi Katılım Noktası Yaşam Döngüsü Eşlem Yöntem Yöntem İzleme İlgisi Kesim Noktası Ön Ürün Yansıma Düzgün Deyim Ardıl İşlem Çizgesi Kurucu İletimi Tekil Kalıp Sınama
ww w. ja
va
dil
Alias Aspect Oriented Programming Assembler Bean Business Logic Collection Configuration File Container Coupling Dependency Injection Design Patterns Factory File Framework Generic Initialization Interface Injection Inversion of Control Join Point Lifecycle Map Method Method Tracing Aspect Pointcut Prototype Reflection Regular Expression Sequence Diagram Setter Injection Singleton Testing
m
4. Terimler Sözlüğü
24
Basılı Kaynaklar: Better, Faster Lighter Java (O’Reilly / ISBN: 0 – 596 – 00676 – 4 ) Justin Gehtland, Bruce A. Tate
i.c o
•
İnternet Kaynakları:
http://www.springframework.org/docs/reference/ http://tools.devchannel.org/devtoolschannel/04/04/15/1457223.shtml http://www.aosd.net http://www.onjava.com/pub/a/onjava/2004/07/14/springaop.html http://martinfowler.com/articles/injection.html http://blog.csdn.net/ylong/ http://www.onjava.com/pub/a/onjava/2004/01/14/aop.html
dil
• • • • • • •
m
5. Kaynaklar
http://cs.hacettepe.edu.tr/~b20021809/Docs/Bil447/kaynak.zip
ww w. ja
•
va
Örnek Uygulama Kaynak Kodları:
25