Professional Documents
Culture Documents
Cepheye Yonelik Program Lama MKURT WwwJavaDiliCom
Cepheye Yonelik Program Lama MKURT WwwJavaDiliCom
i.c
(ASPECT ORIENTED PROGRAMMING)
dil
va
Mücahit Kurt
Hacettepe Üniversitesi Bilgisayar Mühendisliği
ja
Bölümü
w.
ww
Giriş
m
Bu belgede giriş düzeyinde cepheye yönelik programlamadan bahsedilecektir. AOP tüm
dünyada ve ülkemizde geçmişi bayağı eskiye dayanmasına rağmen henüz çok fazla
bilinmeyen bir yöntem ama yazılım sistemlerin karmaşıklığı gerçekleştirimlerini yaptıkları
gereksinimlere koşut olarak her geçen gün biraz daha arttığı için AOP’nin çözüm ürettiği
alanlar insanların başını daha fazla ağrıtmaya başladı ve insanlar AOP ile daha fazla
o
ilgilenmeye başladı. Bu akım en çok uygulama sunucuları alanında oldu, üreticiler AOP
projelerini desteklemeye başladı ve JBoss 4.0 uygulama sunucusunda ağırlıklı olarak AOP
kullanıldı.
i.c
Belge üç ayrı makaleden oluşuyor; birinci makalede cepheye yönelik programlamanın niçin
var olduğu, hangi problemlere nasıl çözümler getirdiğinden bahsedilecektir. Ayrıca cepheye
yönelik programlamanın değindiği bu problemlere cevap üretmeye çalışan bazı mevcut
yöntemlerde açıklanıp karşılaştırma yapılacaktır. İkinci makale giderek popülerliği artan hafif
ağırlıklı sistemlerin AOP çözümleri üzerine olacaktır. Şuan için en gelişmiş AOP
gerçekleştirimi olan AspectJ in bazı sorunları üzerinde durulup bunlara yeni nesil AOP
gerçekleştirimlerinin nasıl cevap ürettiği açıklanacaktır ve AOP nin dünü bugünü ve geleceği
dil
üzerindede açıklamalar olacaktır. En son bölüm Spring J2ee Framework’ünün AOP
gerçekleştiriminin kullanılması üzerine olacaktır.
Bu belgede Türkçe terimlerin kullanılmasına dikkat edilmesine rağmen özellikle AOP ile ilgili
bir çok terimin Türkçe karşılıkları bulunamadı bunun için bu terimler italik harflerle yazıldı.
ja va
w.
ww
Cepheye Yönelik Programlama (Aspect Oriented
m
Programming (AOP))
Özet
Yazılım sistemlerinin çoğu bir çok modül üzerine dağılmış çeşitli ilgilerden (concerns) oluşur.
Bu ilgilerin gerçekleştirimi nesneye yönelik teknikler kullanılarak yapılırsa ortaya
o
gerçekleştirimi ve anlaması zor bir sistem çıkar. Yeni cepheye yönelik programlama (aspect-
oriented programming (AOP)) yöntemleri bu çeşitli modüller üzerine dağılmış ilgilerin modüle
edilmesini kolaylaştırıyor. AOP kullanarak tasarlanması, anlaması ve güncellenmesi kolay
gerçekleştirimler ortaya çıkarabiliriz. AOP bize yüksek üretkenliği, iyileştirilmiş kaliteyi ve
i.c
yeni özelliklerin gerçekleştirimini daha iyi yapabilmeyi sağlıyor.
İlgi özel bir amaç, kavram veya ilgi alanıdır. Teknoloji terimleriyle, tipik bir yazılım sistemi
çeşitli çekirdek ve sistem-düzeyi ilgiden oluşur. Örneğin bir kredi kartı işleyici sistemin
sistem-düzeyi ilgileri loglamayı ele alma, hareket bütünlüğü, yetki kontrolü, güvenlik,
performans vb. olurken çekirdek ilgi ödemeleri işlemedir. Bir çok ilgi (crosscutting concerns
dil
olarak bilinenler) çoklu gerçekleştirim modüllerini etkilemek eğilimindedir. Mevcut
programlama yöntemlerini kullanarak, bir çok modül üzerine yayılmış enine kesen
ilgiler(crosscutting concerns) varsa, gerçekleştirimi yapılan sistem tasarımı, anlaması,
gerçekleştirilmesi ve geliştirilmesi zor bir sistem olarak sonuçlanır.
yazıyorlardı. Maalesef programcılar ellerindeki problemden daha çok özel makine komut
kümeleri üzerinde düşünmek için zaman harcıyorlardı. Yavaşça kullandığımız makineden
soyutlanmamıza izin veren üst düzey dillere doğru göç ettik. Sonra yapısal diller geldi; artık
problemlerimizi işimizi yapabilmek için gerekli olan yordamlar düzeyinde ayrıştırabiliyorduk.
Ancak, karmaşıklık büyüdü ve daha iyi tekniklere ihtiyaç duyduk. Nesneye-yönelik
w.
programlama (NYP) bir sisteme birlikte çalışan nesneler kümesi olarak bakmamıza izin verdi.
Sınıflar gerçekleştirim ayrıntılarını ara yüzler altında saklamamıza izin verdi. Çok şekillilik
(polymorphism) ilişkili kavramlar için ortak bir davranış ve ara yüz sağladı ve temel
kavramların gerçekleştirimine erişmeye ihtiyaç duymaksızın özel davranışları değiştirebilmek
için daha özelleştirilmiş bileşenler oluşturulmasına izin verdi.
Programlama yöntemleri ve diller makineler ile iletişim kuracağımız yolu tanımlar. Her yeni
ww
m
göreceğimiz gibi veya sizin zaten önceden tecrübe ettiğiniz gibi, NYP bir çok modül – çoğu
zaman bağımsız – üzerine dağılmış davranışları ele almada yetersizdir. Zıt olarak, AOP
yöntemleri bu boşluğu doldururlar. AOP ’nin, programlama yöntemlerinin evrimindeki sonraki
büyük adımı temsil etmesi mümkündür.
o
Sisteme bir ilgi kümesi olarak bakmak
Karmaşık bir yazılım sistemine çoklu ilgilerin birleştirilmiş gerçekleştirimi olarak bakabiliriz.
Tipik bir sistem çeşitli türlerde ilgilerden oluşabilir, bu ilgiler iş mantığı, performans, veri
kalıcılığı, loglama ve böcek ayıklama, yetki kontrolü, güvenlik, çok işletim dizili emniyet, hata
i.c
kontrolü vb. olabilir. Ayrıca geliştirme süreci ilgilerini de sayabiliriz bunlar arasında
kavranabilirlik, güncellenebilirlik, takip edilebilirlik ve kolay evrimleştirebilme olabilir. Şekil 1
bir sistemi çeşitli modüller tarafından gerçekleştirimi yapılan ilgiler kümesi olarak gösteriyor.
dil
ja va
w.
Şekil 2 gereksinimler kümesini prizma içinden geçen bir ışık demeti olarak gösteriyor.
Gereksinimler ışık demetini ilgi-tanımlama prizmasından geçiriyoruz, bu prizma her ilgiyi
ayırıyor. Aynı bakış geliştirme süreci ilgileri için de uzatılabilir.
ww
o m
i.c
Şekil 2. İlgi ayrıştırma: Prizma benzeşimi
dil
Bir geliştirici çoklu gereksinimlere cevap olarak bir sistemi oluşturur. Biz bu gereksinimleri
geniş olarak çekirdek modül-düzeyi gereksinimler ve sistem-düzeyi gereksinler olarak
sınıflandırabiliriz. Sistem-düzeyi gereksinimlerinin bir çoğu birbirlerini ve modül-düzeyi
gereksinimleri kesme eğilimindedir. Sistem-düzeyi gereksinimler ayrıca bir çok çekirdek
modülü çaprazlama kesme eğilimdedir. Örneğin, tipik bir kurumsal uygulama yetki kontrolü,
loglama, kaynak havuzlama, yönetim, performans ve depo yönetimi gibi ilgilerden oluşur. Ve
va
bunların her biri çeşitli alt sistemleri çaprazlama keser. Örneğin bir depo yönetimi ilgisi her
durumlu iş nesnesini etkiler.
Daha basit fakat daha somut bir örneği düşünmek gerekirse, bir iş mantığını sarmalayan
sınıfın iskelet gerçekleştirimini düşünebiliriz:
m
// nesnedeki kilidi aç
}
// yukarıdakine benzer diğer işlemler
o
}
i.c
}
}
dil
gerçekleştirimi yapılıyor. Ek olarak bu ilgilerin çoğunun gerçekleştirimi diğer sınıflar içinde
benzer yolla yapılacak. Üçüncüsü, eğer kayıtEt() ve yükle() kalıcılık yönetim işi
yapacaksa sınıfın çekirdek bölümünü mü oluşturmalıdır sorunu çok açık değil.
Belirtiler
ja
Enine kesen ilgilerin mevcut yöntemler kullanılarak yapılan sorunlu gerçekleştirimini bize bir
kaç belirti gösterebilir. Bu belirtileri geniş olarak 2 türde sınıflandırabiliriz:
• Kod Karıştırma : Bir yazılım sistemindeki modüller bir çok gereksinimle eş anlı
olarak etkileşebilir. Örneğin, geliştiriciler çoğu zaman iş mantığı, performans, eş
zamanlama, loglama ve güvenlik hakkında aynı anda düşünürler. Gereksinimlerin
w.
m
üretkenliğe sebep olur.
• Daha az yeniden kullanılabilir kod: Bir modül bir çok ilginin gerçekleştirimini
yapıyor, benzer işlevselliklere ihtiyaç duyan diğer sistemler modülü kullanamayabilir.
• Düşük kod kalitesi: Kod karıştırma saklı problemleri olan kodlar üretmeye sebep
olur. Ayrıca aynı anda bir çok ilgiyi hedef almak bu ilgilerden birinin yada bir çoğunun
o
gerçekleştirimin yeterince etkin yapılamamasına neden olabilir.
• Daha zor evrim: Sınırlı bir bakış ve kısıtlanmış kaynaklar çoğu zaman sadece
mevcut ilgiye hitap eden tasarımlar üretir. Gelecek gereksinimlere hitap edebilmek
gerçekleştirim üzerinde yeniden çalışılmasını gerektirecektir. Ve eğer gerçekleştirim
i.c
modularize değilse bu bir çok modüle dokunmamızı gerektirecektir. Bir çok alt sistem
üzerinde değişiklik yapmak tutarsızlıklara neden olabilir. Ayrıca bu gerçekleştirim
değişikliklerinin hataya sebep olup olmadığını anlayabilmek için teste hatırı sayılır bir
zaman ayırmamız gerekecektir.
Mevcut cevap
Bir çok sistem enine kesen ilgiler içerdiği için gerçekleştirimleri modularize hale getirmek için
bazı tekniklerin ortaya çıkması şaşırtıcı değildir. Bu tekniklerden bazıları arasında mix-in
solutions) vardır.
dil
sınıflar, tasarım örüntüleri(design patterns) ve alana özel çözümler(domain-specific
Mix-in sınıflar ile, örneğin, bir ilginin son gerçekleştirimini erteleyebilirsiniz. Birincil sınıf bir
mix-in sınıf varlığı içerir ve sistemin diğer parçalarının bu varlığı kurmasını sağlar. Örneğin,
bir kredi kartı işleme örneğinde, iş mantığının gerçekleştirimini yapan sınıf bir loglayıcı mix-in
oluşturur. Sistemin bir başka parçası uygun loglama türünü alabilmek için bu loglayıcıyı
kurabilir. Örneğin bir kütük sistemi veya mesajlaşma orta katmanı kullanılarak loglama
va
yapmak için kurulabilir. Loglamanın tabiatı şimdi ertelenmesine rağmen, birleştirici yinede
bütün log noktalarında loglama işlemlerini yaptırmak ve loglama bilgisini kontrol etmek için
gerekli olan kodu içerir.
Framework ler ve uygulama sunucuları gibi alana özel çözümler geliştiricilerin bazı enine
kesen ilgileri module bir yolla ele alabilmelerini sağlar. Örneğin Enterprise JavaBeans(EJB)
mimarisi güvenlik, yönetim, performans ve kap (container) tarafından yönetilen kalıcılık gibi
bazı enine kesen ilgileri ele alabilir. Deployment geliştiricileri veritabanına bean-veri eşleme
w.
Alana özel çözüm özel problemi çözmek için özelleştirilmiş mekanizmalar sunar. Alana özel
çözümlerin bir dezavantajı, geliştiriciler her çözüm için yeni teknikler öğrenmek
ww
zorundadırlar. Çünkü bu çözümler alana özeldir, enine kesen ilgiler direk olarak ele alınamaz
planlanmayan (ad hoc) cevaplar gerekir.
Mimarın İkilemi
İyi sistem mimarları yamalı bir gerçekleştirimden kaçınmak için şimdiki ve gelecekteki
gereksinimleri düşünürler. Ancak bu durum bir probleme sebep olur. Geleceği düşünmek zor
iş. Eğer gelecek enine kesen ilgileri kaçırırsak yani isabet ettiremezsek sistemin bir çok
parçasını değiştirmek yada gerçekleştirimini yeniden yapmak zorunda kalırız. Diğer yandan
düşük olasılıklı gereksinimler üzerinde çok fazla odaklanırsak aşırı tasarlanmış karmaşık bir
sistem ortaya çıkabilir. Böylece sistem mimarları için ikilem: Ne kadar tasarım aşırı
m
tasarımdır? Az tasarıma mı aşırı tasarıma mı doğru eğilmeliyim?
Örneğin, bir mimar başlangıçta ihtiyaç olmayan bir loglama mekanizmasını sisteme dahil
etmelimidir. Eğer etmeliyse, loglama noktaları nereler olacaktır ve hangi bilgiler
loglanacaktır. Benzer bir ikilem, iyileştirme (optimization)-ilişkili gereksinimler için oluşur –
o
performans ile, biz ilerideki dar boğazları nadiren biliriz. Sistemi inşa etmek için genel
yaklaşım; önce sistemin taslağını çıkar ve sonra performansı iyileştirmek için sistem
kullanılırken yeni parçalar ekle. Bu yaklaşım potansiyel olarak taslak da ki bir çok sistem
parçasını değiştirmeyi gerektirir. Zamanla kullanılan parçaların değiştirilmesine bağlı olarak
i.c
yeni dar boğazlar ortaya çıkabilir. Yeniden kullanılabilir kütüphane mimarlarının işi daha zor
çünkü kütüphane için bütün kullanım senaryolarını hayal etmek daha zor bir iştir.
Özet olarak, mimar sistemin ele almaya ihtiyaç duyabileceği her mümkün ilgiyi nadiren bilir.
Ele alınmadan önce gereksinimlerin bilinmesine rağmen bir gerçekleştirimi oluşturabilmek
için gerekli olan özel ihtiyaçlar tamamen mevcut değildir. Böylece mimarlar az / aşırı tasarım
ikilemi ile karşılaşırlar.
dil
Buraya kadarki olan tartışmada enine kesen ilgilerin gerçekleştirimlerinin modularize bir
şekilde yapılmasının daha uygun olacağını söyledik. Araştırmacılar bu işi “ilgilerin ayrılması”
diye daha genel bir konu altında gerçekleştirebilmek için çeşitli çalışmalar yapmışlar. AOP bu
işi yapan yöntemlerden bir tanesi. Yukarıda bahsedilen problemlerin üstesinden gelmek için
ilgilerin açık bir şekilde ayrılması gerekiyor ve AOP bunun için çabalıyor.
va
AOP , çekirdeğinde, ayrık ilgileri bağımlılığın son derece az olduğu bir biçimde
gerçekleştirmemizi ve sonuç sistemi oluşturabilmek için bunları birleştirmemizi sağlıyor. Yani
AOP enine kesen ilgilerin az bağımlı ve modularize edilmiş gerçekleştirimlerini kullanarak
sistemleri oluşturuyor. NYP, zıt olarak, genel ilgilerin (common concerns) az bağımlı,
modularize edilmiş gerçekleştirimlerini kullanarak sistemler oluşturuyor. AOP deki module
etme birimi aspect olarak adlandırılıyor, bu genel ilgilerin NYP deki gerçekleştirimlerinin sınıf
olarak adlandırılması gibidir.
ja
ilgilerden ayırırız. Örneğin daha önce bahsedilen kredi kartı modülü örneğinde, üç ilgi
tanımlayabiliriz: çekirdek kredi kartı işleme, loglama ve yetki kontrolü.
2. İlgi gerçekleştirimi: Her ilgiyi ayrı olarak gerçekleştir. Kredi kartı işleme örneği için,
çekirdek kredi kartı işleme birimi loglama birimi ve yetki kontrolü birimi
gerçekleştirimleri yapabiliriz.
3. Aspectual yeniden birleştirme: Bu adımda bir aspect bütünleştiricisi
modularizasyon birimlerini – aspect oluşturarak yeniden birleştirme kurallarını
ww
dil
AOP enine kesen ilgileri ele alma yöntemleriyle NYP den bir çok yönden ayrılır. AOP de her
ilginin gerçekleştirimi diğer ilgilerin onun üzerinde işlem yaptığının (aspecting) farkında
değildir. Örneğin, kredi kartı işlem modülü diğer ilgilerin onun işlemleri üzerinde loglama ve
yetki kontrolü yaptığının farkında değildir. Bu NYP den kayan güçlü bir modeli gösterir.
Not: Bir AOP gerçekleştirimi başka bir programlama yöntemini kendi taban yöntemi olarak
seçebilir, taban sistemin faydaları da değişmeden kalır. Örneğin bir AOP gerçekleştirimi genel
ilgilerin gerçekleştirimi daha iyi yapıldığı için NYP yi taban sistem olarak seçebilir. Bu
va
gerçekleştirimle genel ilgiler her tanımlı ilgi için NYP tekniklerini kullanabilir. Bu yordamsal
bir dilin bir çok NYP dili için taban dil olarak kullanılmasına benzer.
Örme örneği
Örücü, işlemci, ayrık ilgileri örme olarak bilinen bir işlemde bir araya toplar. Örücü diğer bir
deyişle farklı çalışma-mantığı parçalarını ona sağlanan bazı kriterlere göre bir araya getirir.
ja
Kod örmeyi göstermek için kredi kartı işleme sistemi örneğimize bakalım. Kısalık için sadece
kredi ve borç işlemlerini düşünelim. Ayrıca uygun bir loglayıcının bulunduğunu varsayalım.
m
public interface Loglayıcı {
public void log(String mesaj);
}
İstenilen birleştirme aşağıdaki örme kurallarını gerektiriyor, burada doğal dille açıklanmıştır:
o
1. Her genel (public) işlemin başlangıcını logla
2. Her genel işlemin tamamlanışını logla
3. Her genel işlem tarafından fırlatılan bütün hataları logla
i.c
Örücü sonra bu örme kurallarını ve ilgi gerçekleştirimlerini aşağıdaki birleştirilmiş kodun
dengini üretmek için kullanacaktır:
dil
throws GeçersizKartHatası, YetersizBakiyeHatası,
KartZamanAşımınaUğramışHatası {
_loglayıcı.log("KrediKartıİşleyicisi.borç(KrediKartı,
Para)’nın başlangıcı "
+ "Kart: " + kart + " Miktar: " + miktar);
// Borç Mantığı
va
_loglayıcı.log("KrediKartıİşleyicisi.Borç(KrediKartı,
Para)’nın tamamlanışı "
+ "Kart: " + kart + " Miktar: " + miktar);
}
System.out.println("Kredi Verme");
_logger.log("KrediKartıİşleyicisi.Kredi(KrediKartı,
Para)’nın başlangıcı"
+ "Kart: " + kart + " Miktar: " + miktar);
w.
// Kredi mantığı
_logger.log("KrediKartıİşleyicisi.Kredi(KrediKartı,
Para)’nın tamamlanışı "
+ "Kart: " + kart + " Miktar: " + miktar);
}
}
ww
m
AOP dil belirtimi
Daha üst bir düzeyde bir AOP dili iki bileşeni belirler:
• İlgilerin gerçekleştirimi: Ayrık bir gereksinimi kod içine eşleriz böylece derleyici
o
onu çalıştırılabilir kod şekline çevirebilir. İlgilerin gerçekleştirimleri yordam belirtimleri
biçiminde olabilir böylece AOP ile C, C++, Java gibi geleneksel dilleri kullanabiliriz.
• Kural belirtimlerini örme: Son sistemi oluşturmak için birbirinden bağımsız olarak
gerçekleştirimi yapılmış ilgileri nasıl birleştireceğiz. Bu amaç için, bir gerçekleştirim
i.c
son sistemi farklı gerçekleştirim parçalarını birleştirerek oluşturmak için belirtimi
yapılmış kurallara bunun içinde bir dili kullanmaya yada oluşturmaya ihtiyaç
duyar.Örme kurallarını belirlemek için gerekli olan dil gerçekleştirim dilinin bir uzantısı
veya tamamen farklı bir şey olabilir.
dil
2. Sonuç bilgiyi çalıştırılabilir kod biçimine çevir
Bir AOP gerçekleştirimi örücüyü çeşitli yollarla gerçekleştirebilir, bunlardan birisi kaynak-
kaynağa çevirmedir. Burada, örülmüş kaynak kodu üretmek için ayrı aspect ler için yazılmış
kaynak kodu ön işlemeye alırız. Sonra AOP derleyicisi son çalıştırılabilir kodu üretmek için bu
çevrilmiş kodu taban dil derleyicisine yedirir. Örneğin, bu yaklaşımı kullanarak, Java-tabanlı
va
bir AOP gerçekleştirimi ayrı aspect leri önce Java kaynak koduna çevirir, sonra Java
derleyicisinin bu kodu bayt kodlarına çevirmesini sağlar. Aynı yaklaşım bayt kod düzeyinde
örme de yapabilir; hepsinden sonra, bayt kod hala bir çeşit kaynak koddur. Hatta kullanılan
çalıştırma sistemi – bir sanal makine (Virtual Machine) (SM) gerçekleştirimi – aspect lerin
farkında olabilir. Java-tabanlı AOP gerçekleştirimi için bu yaklaşımı kullanma, örneğin, SM
önce örme kurallarını yükler sonra bu kuralları sonradan yüklenmiş sınıflara uygular. Diğer
bir deyişle, SM just-in-time aspect örme yapabilir.
ja
farkında olamayabildikleri için yeni aspect ler oluşturarak sisteme daha yeni
işlevselliklerin eklenmesi kolaydır. Hatta, sisteme yeni bir modül eklendiği zaman,
varolan aspect ler onları enlemesine keser ve bu tutarlı bir evrimin oluşmasına yardım
eder.
• Tasarım kararlarının geç bağlanması: Mimarların az / aşırı tasarım ikilemini
hatırlayalım. AOP ile bir mimar gelecek gereksinimler için karar vermeyi erteleyebilir
ve bunların gerçekleştirimini ayrı aspect ler olarak yapabilir.
• Daha çok yeniden kullanımı: Çünkü AOP her aspect i ayrı bir modül olarak
gerçekleştirir, her ayrı modül daha az bağımlıdır. Örneğin, farklı bir gereksinimle ayrı
m
bir loglama aspect inde veritabanı ile modül etkileşimini kullanabiliriz. Genel olarak,
az bağımlı gerçekleştirim daha yüksel kod yeniden kullanılabilirliğinin anahtarıdır ve
AOP NYP ile yapabildiğimizden daha az bağımlı gerçekleştirimler ortaya çıkarmamızı
etkin kılar.
o
AspectJ: Java için bir AOP gerçekleştirimi
Aspectj, Xerox PARC dan Java için bedava olarak mevcut olan bir AOP gerçekleştirimidir,
genel amaçlı bir AO (aspect-oriented) Java uzantısıdır. AspectJ ayrı ilgilerin
gerçekleştiriminde dil olarak Java yı kullanır ve örme kuralları için Java ya uzantılar tanımlar.
i.c
Bu kurallar pointcuts, birleşme noktaları(join points), advice ve aspect isimleri altında
belirtilir. Birleşme noktaları bir programın çalışmasındaki özel noktaları tanımlar, pointcut bir
dil yapısıdır ve birleşme noktalarını belirtir, advice pointcut larda çalıştırılacak olan aspect
gerçekleştirim parçasını tanımlar ve aspect bu primitive leri birleştirir.
Ek olarak, AspectJ ayrıca diğer aspect ler ve sınıfların çeşitli yollarla aspect haline
getirilmesine izin verir. Yani, taban sınıfların ve ara yüzlerin gerçekleştirimini yapmak için bir
dil
sınıf tanımladığımız gibi yeni veri üyeleri ve yeni yöntemler tanıtabiliriz.
AspectJ’in örücüsü – bir aspect derleyicisi – farklı aspect leri birleştirir. AspectJ derleyicisi
tarafından oluşturulan son sistem saf Java bayt kodlarıdır ve uyumlu herhangi bir JSM (Java
Sanal Makinesi) de çalışabilir. AspectJ’in hata ayıklayıcı (debugger) ve bazı IDE ler ile
bütünleşmesini sağlayan araçları da vardır.
Aşağıda, yukarıda doğal dille tanımladığımız örücü için loglama aspect nin bir AspectJ
va
gerçekleştirimi var. Burada dikkat edilmesi gereken nokta kredi kartı işlemenin loglama
hakkında hiçbir şey bilmediğidir.
pointcut publicOperation():
ja
execution(public * KrediKartıİşleyicisi.*(..));
miktar);
}
m
after (KrediKartı kart, Para miktar) throwing (Exception e):
publicOperationCardAmountArgs(kart, miktar) {
logOperation("Hata " + e,
thisjoin point.getSignature().toString(), kart,
o
miktar);
}
i.c
private void logOperation(String durum, String işlem,
KrediKartı kart, Para miktar) {
loglayıcı.log(durum + " " + işlem +
" Kart: " + kart + " Miktar: " + miktar);
}
}
dil
AOP sadece tasarım noksanlıklarına mı hitap ediyor? AOP de, her ilgi gerçekleştirimi
kendisinin başka ilgiler tarafından aspect lendiği gerçeğinin farkında değildir. Bu farkında
olmama AOP yi NYP den ayırır. AOP de birleştirmenin akışı enine kesen ilgilerden ana ilgiye
doğrudur oysa NYP tekniklerinde akış ters yöndedir. Ancak şu da vardır ki NYP ve AOP çok iyi
bir biçimde beraber olabilir. Örneğin bir mix-in sınıfı AOP mizin uygunluk düzeyine bağlı
olarak hem AOP hemde NYP ile bir birleşim olarak kullanabiliriz. Her iki durumda da bir enine
va
kesen ilginin gerçekleştirimini yapan mix-in sınıf kendisinin elle birleştirilmiş bir sınıf veya
kural tabanlı birleştirme kullanarak oluşturulmuş bir aspect in parçası olduğu bilgisine ihtiyaç
duymaz. Örneğin, bir loglama ara yüzünü bazı sınıflar için bir mix-in veya diğerleri için bir
loglama aspect i olarak kullanabiliriz. Böylece NYP den AOP evrimsel bir yol olur.
mevcut yolları ve onların noksanlıklarını ele aldık. Ayrıca AOP nin bu problemlerin üstesinden
nasıl geldiğini inceledik. AOP yöntemi enine kesen ilgilerinin gerçekleştirimlerini modularize
ediyor ve daha iyi daha hızlı bir yazılım gerçekleştirimi üretiyor. Eğer sizin yazılım
sisteminizde bir çok enine kesen ilgiden oluşuyorsa, sizde AOP, onun gerçekleştirimi ve
faydaları hakkında daha fazla şey öğrenmeyi düşünmelisiniz.
w.
m
AOP frameworklerinin yeni ürünleri ile Advice ları
dinamik olarak uygulanması
o
Özet
AOP güçlü bir şekilde modularize edilmiş programlar sunarken ve Java platformu için
sağlam, zengin özelliklere sahip gerçekleştirimler AspectJ de mevcutken, AOP henüz
i.c
ortalama bir Java programcısının araç kutusuna girebilmiş değildir. AOP şimdiye kadar hep
konferanslarda ilginç bir merak konusu ve herkesin yapacaklar listesinde hakkında daha
fazla şey öğrenilecek bir şey olarak kalmıştır. Sonra hafif ağırlıklı (lightweight), saydam
uygulama sunucularına olan ilgi dalgası ile birlikte ortaya, geliştiricilere advice ları
öncekinden daha devingen ve esnek bir biçimde uygulama imkanı veren özellikleri ile birlikte
yeni AOP gerçekleştirimleri çıktı. Bu yazıda yeni AOP gerçekleştirimleri ile eskileri
karşılaştırılıyor, yeni özelliklerin oturduğu yerler açıklanıyor ve Java platformunda AOP nin
geleceği inceleniyor.
dil
Modülarizasyon programlamayı mümkün kılıyor. Hesaplamanın tarihi boyunca düzenleme
araçlarının geçit töreni – üst-düzey dil, yordam, nesne – bizim yükselen bir oranda daha açık
ve güçlü kodlar yazmamızı sağlamıştır. Bu aynen bilgisayar donanımında olduğu gibi,
va
yeteneklerimiz iyileştiği zaman çıtayı biraz daha yükseltiyoruz ve şimdi yirmi birinci yüz
yıldayız ve hala daha çabuk ve daha ucuza geniş programlar üretmek için çaba sarf ediyoruz.
Sonraki adım ne, bizim yeteneklerimizi bir sonraki düzeye alacak programlarımızı
yapılandıracak yeni yol?
AOP bu soruya cevap girişimlerinden bir tanesi. 1990 ların sonlarında Xerox PARC (uğurlu bir
soy!) da düşünüldü, AOP sıradan bir program boyunca tekrar eden kod satırlarına karşılık
ja
gelen enine kesen ilgileri modularize etmek için tasarlanmıştır. AOP tüm bu enine kesen
ilgileri tek bir yer içince topluyor, bir AOP yapısı sınıfa benzer olarak advice olarak biliniyor.
AspectJ de ilk olarak Xerox PARC’dan çıktı ve şimdi Eclipse kurumu bünyesinde geliştiriliyor,
AspectJ Java için bir AOP gerçekleştirimidir. AspectJ dikkate değer yayımlar boyunca giden
ve bazı üçüncü parti araçlar tarafından da desteklenen iyi tasarlanmış sağlam bir framework
w.
tür. Son zamanlarda, uygulama sunucusu tasarımcıları şunu anladılar ki – AOP tarafları
yıllardır söylüyor – AOP, uygulama sunucularının remoting, kalıcılık ve hareket gibi
işlevselliklerini gerçekleştirmek için doğal bir yol olarak görünüyor, eğer gerçekleştirimi eşit
olarak devingen ise AOP Java platformunun devingen ortamlarında daha kolay
kullanılabiliyor.
ww
m
Öncelikle bağlamın hazırlandığını göstermek için basit bir test yazalım:
o
İstemciTaraflıBağlam.varlık().yerleştir(“kullanıcıID”,
”ali”);
BağlamAlıcı proxy = (BağlamAlıcı)
ProxyFabrikası.varlık().proxyAl(“BağlamAlıcı”);
i.c
assertEquals(“ali”, proxy.al(“kullanıcıID”));
}
}
Testimizde öncelikle bağlama bir yetki kontrolü söz dizimi koyuyoruz. Sonra, hizmetimize bir
singleton proxy fabrikasından proxy alıyoruz. (Bu Service Locator örüntüsünün bir örneğidir,
dil
burada fabrika uzak bir hizmet için proxy inşa edilmesinin karmaşıklığını istemciden
saklıyor.) Hizmet, BağlamAlıcı nın bir varlığı, basit olarak istenen değeri kendi
bağlamından döndürüyor. Testin son satırında yetki kontrolü söz diziminin olması gereken
değerde olup olmadığını kontrol ediyoruz.
Bu örnekle ilgili birkaç yorum yapacak olursak. Birincisi, bu test epeyce anlamsız
görünmesine rağmen gerçek bir uygulamada biz bağlamı onu yazdığımız yerden farklı bir
yerden okuruz ve aslında bağlam bilgisini geri göndermek yerine onu sunucu tarafında
va
kullanırız.
İkincisi, bu örnek bir çok yerde singleton örüntüsü kullanılmasına rağmen, eğer biz geniş
olarak kullanılan bir framework yazıyorsak kesinlikle onun API lerinde singleton
kullanmamalıyız. Singleton somut bir sınıf olmak için tek bir varlığının olmasına gereksinim
duyar, oysa sınıfların gerçekleştirimlerini istemciyi etkilemeden değiştirebilmek için sınıflar
daima ara yüzler arkasında saklanmalıdırlar. Ayrıca eğer singleton referansı herkese açıksa
ja
(global) gerekli olduğu zaman, test esnasında mesela, farklı bir varlığı kullanan bir nesneyi
yapmak daha da zordur.
saklandığı yerdir:
m
public Map bağlamAl() {
return mBağlam;
}
}
o
BağlamAlıcı ara yüzü sadece aşağıdaki BağlamAlıcı gerçekleştiriminin bir varlığını
oluşturur ve döndürür:
i.c
public class BağlamAlıcıGerc implements BağlamAlıcı {
public Object al (Object anahtar) {
return SunucuTaraflıBağlam.varlık().al(anahtar);
}
}
return mBağlam.get(anahtar);
}
}
Aspect BağlamGeçirici {
before(): execution(* BağlamAlıcıGerc.*(..)) {
SunucuTaraflıBağlam.varlık().bağlamKur(İstemciTaraflıBağlam.
varlık.bağlamAl());
}
}
Bu aspect tek bir parça advice içeriyor. Bu advice yöntem adviced olmadan önce çağırılan
m
before() advice dır. execution() ifadesi kendilerinden önce advice ın çalıştırılacağı
yöntemleri belirliyor. Bu durumda BağlamAlıcıGerc.*(..) ifadesi, poincut olarak ifade
ediliyor, BağlamAlıcıGerc sınıfının her yönteminden önce advice ın çalışmasına neden
oluyor. Asıl işin yapıldığı advice ın gövde kısmında bağlamın nasıl geçirildiğini görüyoruz: var
olan bağlam İstemciTaraflıBağlam dan SunucuTaraflıBağlam kopyalanıyor.
o
Elbette gerçek bir framework de sunucu tarafı farklı bir sanal makine de olacak ve yapmamız
gereken biraz daha fazla iş olacak.
i.c
üstünde bazı hoş avantajlar verdi. Bir ara yüzü gerçekleştirmek için bir hizmete gereksinim
duymadan (Bir EJB(Enterprise JavaBean) bileşenin bir SessionContext almak için
yapmak zorunda olduğu) istemci ve sunucu tarafının bağlam-ilişkili sınıflara olan bağımlılığını
azaltıyor. Aslında biz bağlam geçişini framework ün kalan kısmından ayırmış olduk, böylece
eğer ileride bağlama ihtiyacımız olmaz ise o zaman sadece uygulamamızı
BağlamGeçirici aspect i olmadan derlememiz yeterli olacaktır. Yukarıdaki test başarısız
olacaktır ama her şey derlenebilecektir ve bağlam geçişine gereksinim duymayan kod normal
AspectJ AOP gerçekleştirimi ne kadar güçlü olursa olsun geliştiriciler daima isteyecek yeni
şeyler bulabilirler. Bunlardan en kesin olanı şuan önümüzde; aspect ler Java da yazılamıyor.
Yani sadece yeni bir tasarım öğrenmiyoruz ayrıca yeni bir dil söz dizimi öğreniyoruz ve
va
geliştriciler sadece AspectJ anlamak zorunda kalmıyorlar ayrıca kullandıkları araçlarıda
anlamak zorunda kalıyorlar. Aspect lerin tamamen Java ile yazılabilmesi çok hoş olacak.
AspectJ’in advice ları yöntemlere bağladığı yol – advice edilecek yöntemlerin adları ile
eşleşen bir pointcut ifadesi yazmak—geleneksel Java programlarının anlamını başka bir yola
çeviriyor. Sıradan Javada, bir yöntem ismi basit bir tanımlayıcıdır, kullanılan yöntemin
amacını okuyucuya iyi bir şekilde sunmanın en iyi yolu iyi bir isim seçmektir. Fakat AspectJ
ja
de yöntem isimleri (ve sınıf, yapıcı ve alan isimleri)’nin iki amacı vardır: iletişim ve eşleşen
ifadelerin hedefi olarak hizmet verme. Aspect ler içeren bir program da bir yöntemin ismini
değiştirmek yöntemin edilmesi gerektiği halde advice edilmemesine veya bunun tam tersine
sebep olabilir. Yöntem ekleyip çıkarmak da aspect lerle ilgili istenmeyen durumlara sebep
olabilir. Bazı araçlar AspectJ ile ilgili bu sorunları ele ala biliyor fakat aspect ler hayatımızı
umut ettiğimiz kadar basit yapmıyor. Ve eğer pointcut lar ile tanımlayıcılarımızı uyumlu
w.
tutmak istiyorsak bazı tanımlayıcılarımızı değiştirmek zorunda kalırız veya daha kısa pointcut
lar yazarız, buda programımızın okunurluğundan ödün verebilir. Başka bir yol varmı?
Dağıtık, çok kullanıcılı sistemler üzerinde olan bizim küçük örneğimizden daha karmaşık
uygulamaları düşündüğümüz zaman farklı bir sorun daha ortaya çıkıyor. Bizim örneğimizdeki
advice sanal makinede BağlamAlıcıGerc in her varlığına uygulanıyormuş gibi görünüyor.
ww
m
yada aspect ler cıkarabilmekten veya programın yapısını tekrar derleme gerektirmeden
aspect eklenebilecek şekilde değiştirmekten hoşlanabiliriz. Bunu AspectJ ile yapamıyoruz
çünkü AspectJ advice ları advised sınıflar içerisine derleme zamanında örüyor. Bu
davranışlarını yeniden derleme gerektirmeyen konfigürasyonla değiştirmek için çabalayan
nesneye yönelik pratiği ihlal ediyor.
o
Kurumsal yazılımlar dünyasındaki son zamanlardaki eğilim hafif ağırlıklı, saydam orta
katmanlara doğru gidiyor. Bir çok geliştirici grubları EJB nin artan karmaşıklığı yüzünden bir
çıkış yolu arıyor ve enerjilerini hizmetleri üretmek için yazılmak veya üretilmek zorunda olan
i.c
boilerplate kod miktarını ve konfigürasyonu azaltmayı amaçlayan framewok ler için
harcıyorlar. Bunların açık kaynak dünyasındaki yüksek profilli örnekleri arasında JBoss 4.0,
Spring, PicoContainer ve HiveMind var. Büyük uygulama sunucusu üreticileri de bu projeler
ile ilgileniyor, BEA’nın Beehive projesine desteği gibi. Bir çok web hizmeti framework ü,
bedava veya ticari, EJB-tabanlı bir kab’ a benzeyen veya onun yerine olan basitleştirilmiş bir
kab sağlıyor. Ve sonunda Mayıs 2004 de Sundan Linda DeMichiel’in EJB 3.0 ın eski EJB
API’sinin çoğunu silip süpürdüğünü açığa vurmasıyla eğilim yeni bir önemlilik düzeyine ulaştı.
dil
Bütün bu etkinlikler uygulama sunucusu tasarımındaki araştırmaların çeşitli ilginç alanlarına
güç verdi. Burada vurgulamaya çalıştığımız nokta sonunda AOP nin orta katman
uygulamalarda çok etkin olduğunun anlaşılmasıdır. Bir çok uygulama sunucusu işlevsellikleri
gayet açık ve mantıklı bir biçimde aspect ler olarak ifade edilebilir. Bağlam geçirme,
remoting, güvenlik ve hareket gibi işlevsellikler sıradan bir nesnenin yönteminin
çağırılmasında yöntem çağrılmasının çevresinde(önce ve/veya sonra) olan işlevsellikler
olarak düşünülebilir. Aspect-oriented programlama bir uygulama sunucusu tasarımcısının bu
va
özellikleri soyut sınıflardan kalıtmak veya ara yüzleri gerçekleştirmek için bir hizmet
sağlayıcısına gereksinim duymadan sağlayabilmesini sağlar.
Uygulama sunucusu ortamlarındaki AOP üzerindeki şuandaki ışıldama ile birlikte yukarıda
tartışdığımız AspectJ’in kısıtlamaları daha da önemli oluyor. Şuanda ve geçen yıllarda AOP
nin gelecek geliştirimler üzerindeki önemi görülünce bu kısıtlamaları ele alan bir çok yeni
AOP framework ü geliştiriliyor. Şimdi bağlam geçirme örneğimizin gerçekleştirimini bu yeni
ja
framework lerden bir tanesi olan JBoss AOP ile yeniden yapalım ve karmaşık, devingen
uygulamaların taleplerine nasıl dayandığını görelim.
sunucusunda AOP kullanmak için gelmekle birlikte AspectJ gibi herhangi bir Java
programında kullanılabilen bağımsız bir framework tür. AspectJ ile karşılaştırmasını görmek
için daha önce AspectJ ile yaptığımız örneğimize dönelim. Birkaç istenmeyen durumla birlikte
AspetJ ile kullandığımız kodun aynısını kullanacağız. Şimdi advice ların JBoss AOP de nasıl
olduğunu görelim:
m
}
o
koyduğumuz bağlam geçirme kodunun aynısını koyuyoruz. Yöntemin son satırı kontrolü
framework e döndürüyor. Burada kötü bir durum var ama farklı bir durumda gerçek yöntem
çağrısından dönen değeri başka bir şey ile değiştirebiliriz.
i.c
Bu kadar, JBoss AOP de advice sadece bir Java sınıfı ve böylece öğrenilecek yeni bir söz
dizim yok ve bütün diğer java kodumuzla çalışan geliştirme ortamımızda da çalışıyor. Bu
bizim yukarıdaki ilk itirazımızı ele alıyor.
Peki advice ı bir yöntem çağrısına bağlayan AspectJ deki pointcut ların denkliğ nerede? JBoss
AOP bunu yapmak için 2 farklı yol öneriyor. Birincisi genellikle jboss-aop.xml diye
adlandırılan bir konfigürasyon kütüğü kullanıyor:
<aop>
dil
<bind pointcut="execution(* *->@contextual(..))">
<interceptor class="BağlamGecici"/>
</bind>
</aop>
va
Bu kütük genellikle sınıfların yüklenme zamanında okunuyor bunun için tekrar derlemeden
advice ekleyip silebilir ve advice ın uygulandığı yöntemleri değiştirebiliriz. Bunun yerine eğer
istersek AspectJ de yaptığımız gibi aspect lerimizi derleyebiliriz. Bu kütük o zaman yüklenme
zamanında değil derleme zamanında yorumlanır.
Advice larımızı ilişkilendirmenin diğer yolu daha esnek. JBoss AOP ye advice ı hangi
yöntemlere uygulamak istediğimizi anlatmak için hala jboss-aop.xml de bir pointcut a
ja
ihtiyacımız var:
<aop>
<prepare expr="execution(* *->@contextual(..))"/>
</aop>
w.
Ama bu hic bir sınıfa advice uygulamıyor, sadece advice ın uygulanacağı sınıfları hazırlıyor.
Sınıfımız advice ın uygulanabilmesi için hazırlandı, biz sınıfımıza kendi kodumuz içinde
herhangi bir zamanda advice ı uygulayabiliriz.
m
BağlamGecirici());
return advised;
}
}
o
AspectJ örneğinde ProxFactory gösterilmemişti çünkü o sadece BaglamAlıcıGerc in
bir varlığı olarak inşa edilip döndürülüyordu. Burada biz yeni bir advice oluşturup onu advice
ı uygulamak istediğimiz varlıkla ilişkilendiriyoruz. Bu yöntemle advice ı uyguladığımız nesneyi
istediğimiz bağlamda kullanmakta tamamem özgürüz. Advice ın uygulandığı ve
i.c
uygulanmadığı iki ayrı varlığa sahip olabiliriz veya tek bir varlıktan gerekli olduğunda advice ı
çıkarabilir veya ekleyebiliriz.
Eşleme ifadeleri kullanarak advice ı nesneler ile ilişkilendirme konusu ilgili olarak nasıl özgür
olduğumuz konusunda daha bir şey söylemedik. Ama şu farkedilmiştir ki, jboss-aop.xml
kütüğünde kullanılan eşleme ifadelerinde herhangi bir sınıf neya yöntem adından
bahsedilmiyor. JBoss AOP ile de AspectJ deki gibi özel sınıflara, yöntemlera vb. hitap eden
dil
pointcut ların tanımı yapılabiliyor ama bu örnekte biz bunu kullanmadık. Bunun yerine biz
advice ı uygulamak istediğimiz yönteme eklediğimiz bir nota hitap eden @contextual diye
bir gösterim kullandık. Bu aşağıdaki BağlamAlıcıGerc in içinde görülüyor:
JBoss AOP notu iki tane @ işaretli javadoc tag leri gibi gürünüyor. JBoss AOP’nin
AnnotationC adlı aracı Java kaynak kodunu ayrıştırıyor ve bulduğu notları genellikle
ja
metadata-aop.xml adlı bir kütük içine derliyor. Bu bize en çok esnekliği advice larla
kodumuzu ilişkilendirirken verir: AspectJ tarzındaki poincut lar işi yaparken advice ı
ilişkilendirildiği kodu değiştirmeden ilişkilendirebiliriz. Eğer bir yöntemler kümesine advice
uygulamak istiyorsak bir pointcut yazmak anlamsızdır bunun yerine burada gösterildiği gibi
ya hedef yöntemlere notu yerleştiririz veya metadata-aop.xml kütüğünü kendimiz
w.
yazarız.
J2SE 1.5 (Tiger) ile gelen yenilikleri okuduysak JBoss AOP notlarının J2SE 1.5 notları (JSR
175 de belirtilmiştir) gibi davrandığını farketmişsinizdir. Aslında J2SE 1.5 in son sürümü hazır
olduğunda JBoss AOP JSR 175 notlarını i destekleyecektir, kendi notlama sistemini yapması
gereksizdir ve ön derleme ihtiyacını ortadan kaldırır.
ww
Yazılımda, başka yerlerde de olduğu gibi, güç ve esneklik bir bedelle gelir. JBoss AOP de de
yapıldığı gibi tasarımda bazı sonuclara ulaşmak için vazgeçilen şeyler yeni nesil AOP
framework lerinde yapılan tipik bir şeydir. Advice ı çalışma zamanında ilişkilendirmek kod ile
AOP framework ü arasındaki ayrımı kırar. Advice hedeflendirmeyi koddan açık olarak
ayırmak kodu değiştirmeyi veya ek bir dolaylama katmanının karmaşıklığını gerektirir. Fakat
tek iyi iş şudur ki bize ihtiyacımız olanı veriyor ve yeni framework ler üzerinde sarf edilen
çaba bu özelliklere uygulama sunucusu dünyasında ihtiyaç duyulduğunu daha açık bir hale
getirdi.
Rekabet
m
JBoss AOP burada örnek olarak verildi ama JBoss AOP tek ciddi ikinci-nesil AOP framework ü
değildir. Aşağıdaki tablo Java platformu için mevcut olan diğer AOP gerçekleştirimlerini ve
onların özelliklerini listeliyor.
o
AOP framework leri
i.c
Örme Zamanı (Weaving Derleme/Yükleme- Derleme/Yükleme- Derleme/Yükleme/Çalışma- Çalışma Çalışma
time) zamanı zamanı zamanı Zamanı Zamanı
dil
cflow interception ları
Bir çok AOP framework ü uygulama sunucuları ile ilişkili olsalarda tek başlarınadır. Sadece
Spring framework ü hariç veya en azından ayrı olarak mevcut değildir. “AOP Alliance” bazı
framework ler tarafından gerçekleştirimi yapılan AOP için genel bir API dir.
Son olarak tablo framework lerle ilişkili olan uygulama sunucusu üreticileri veya
geliştiricilerini listeliyor. IBM tarafından kurulan Eclipse Foundation AspectJ i güncelliyor ve
IBM den WebSphere e AspectJ desteği eklemesi bekleniyor. İlk önce bağımsız olan
AspectWerkz projesi şuanda BEA tarafından destekleniyor ve BEA nın Jrockit sanal
makinesini destekliyor. JBoss AOP de JBoss dan geliyor ve JBoss 4.0 da kapsamlı olarak
m
kullanılacak.
Bu tablo çok ayrıntılı değil. Daha bir çok AOP gerçekleştirimi ve ilintili projeler mevcut
bazıları güçleniyor, bazıları daha yeni duyuruluyor ve bazılarıda yavaş yavaş soluyor.
o
Buradan nereye gidiyoruz?
AOP için bir çok seçenek var, hangisini kullanmalıyız? Farklı projelerde farklı framework ler
uygun oluyor. Daha karmaşık projeler özellikle dağıtık, çok kullanıcılı sistemler muhtemelen
daha yeni olan framework lerin devingen özelliklerini kullanmak isteyeceklerdir.
i.c
Bu framework lerin çoğu gerçekten tek başlarına olmalarına rağmen, uygulama sunucusu
geliştirmek için AOP kullanan bir çok kuruluş kendi uygulama sunucuları ile benzer AOP
framework ünü seçiyorlar. AOP’nin Java dünyasındaki geleceği belki uygulama sunusu
pazarının geleceğidir. AOP Alliance veya diğer standartlarla AOP framework leri arasında
kolay hareket etmenin mümkün olup olmayacağını söylemek için çok erken ama farklı
framework lerdeki yaklaşım çeşitliliğine bakılırsa biraz zor görünüyor.
dil
Ve AOP orta katmanının dışınıda etkileyebilecekmi? Muhtemelen. Bir çok geliştirici AOP
hakkında düşünmeden AOP kullanılan orta katmanlarda çalışacak. Fakat her proje şimdi veya
daha sonra mutlaka motorun kapağını açmaya ihtiyaç duyar, AOP’nin orta katmanda neler
yapabildiğini görünce muhtemelen bir çoğumuz onu yazılım sistemimizin her yerinde
kullanacağız. Orta katmanın her yerde yaygınlaşması AOP için büyük bir şans olabilir.
m
Gerçekleştirimi
Spring’in AOP paketi AOP Alliance uyumlu bir aspect-oriented programming gerçekleştirimi
sağlar. Bu paket ile, yöntem-interceptor lar pointcutlar tanımlayarak kodumuzdaki
bağımlılıkları rahatlıkla engelleyebiliriz. Kaynak düzeyi metadata işlevselliğini kullanarak
o
bütün davranışsal bilgi türlerini kodumuza dahil edebiliriz.
AOP program yapısı hakkında farklı bir düşünme yolu sağlayarak NYP yi tamamlıyor. NYP
uygulamaları nesneler hiyerarşisinde parçalarken, AOP programları aspect ler veya ilgiler
i.c
olarak parçalıyor. Bir ilgi özel bir amaç, kavram veya ilgi alanıdır.
dil
rağmen), amaç AOP gerçekleştirimi ile Spring IoC arasında yakın bir bütünleştirme
sağlayarak kurumsal uygulamalardaki genel problemleri çözmektir.
• Bildirimsel kurumsal hizmetler sağlamak için özellikle EJB bildirimsel hizmetlerin yerine
kullanılmak üzere. En önemli hizmet Spring’in hareket soyutlamasını oluşturan
bildirimsel hareket yönetimidir.
va
• Kullanıcıların aspect leri gerçekleştirmelerine izin vererek onların NYP ile birlikte AOP yi
kullanmalarını tamamlamak.
Spring’in AOP desteğinin ilk amacı POJO lara J2ee hizmetleri sağlamaktır. Bu JBoss 4 ün
amacı ile benzerdir. Ancak Spring AOP’nin uygulama sunucuları arasında taşınabilen
avantajları vardır böylece üreticiye dönük bir bağlanma söz konusu değildir. Spring AOP hem
web kabında hem de EJB kabında çalışır ve WebLogic, Tomcat, JBoss, Resin, Jetty, Orion ve
ja
diğer bir çok uygulama sunucusunda ve web kabında başarı ile kullanılmıştır.
Aşağıda bazı AOP kavramlarını anlatmaya çalışacağım ama çoğunun Türkçe karşılıkları
hakkında henüz çok fazla bir fikrim yok:
w.
• Advice: AOP framework tarafından özel bir birleşme noktasında yapılan hareket.
Advice ların “around”, “before” ve “throws” diye ayrılan türleri vardır. Spring’in de
içinde bulunduğu bir çok AOP framework ü advice ı interceptor olarak modeller.
• Pointcut: Bir advice’ın uygulanacağı birleşme noktaları kümesi. Bir AOP framework ü
kullanıcının örneğin düzenli ifadeler kullanarak pointcut lar belirleyebilmesini
sağlamalıdır. Durağan pointcut lar yöntem imzalarıyla ilgilenirler, devingen pointcutlar
hesaplandıkları noktada yöntem argümanlarınıda hesaba katabilirler. Pointcutlar
interceptor lardan ayrı olarak tanımlanır böylece standart bir interceptor in değişik
uygulama ve kod bağlamlarına uygulanabilmesi sağlanır.
m
• Giriş: Advice’ın uygulandığı bir sınıfa yöntemler veya alanlar eklemek. Spring advice
ların uygulandığı nesnelere yeni ara yüzler tanıtabilmemize izin verir.
• Hedef Nesne: Birleşme noktası içeren nesne ayrıca advised veya proxied nesne olarak
da söylenebilir ben bunları advised nesneyi advice (lar)ın uygulandığı nesne olarak
çevirdim.
o
• AOP Proxy: Advice içeren AOP framework tarafından yaratılmış nesne. Spring de AOP
proxy bir JDK devingen proxy veya CGLIB proxy olabilir.
• Örme(Weaving): Advice (lar) ın uygulandığı nesneyi yaratabilmek için aspect leri
birleştirme. Bu işlem derleme zamanında yapılabilir (örneğin AspectJ derleyicisi
i.c
kullanılarak) veya çalışma zamanında yapılır. Spring diğer saf java olan AOP framework
leri gibi örme işlemini çalışma zamanında yapar.
Spring durumsal(stateful) (her advised nesne için bir varlık) ve durumsuz(stateless) (bütün
advice lar için bir valık) interceptor ların her ikisini de destekler. Spring AOP yi devingen
proxy ler veya çalışma zamanında CGLIB bayt kod üretimi kullanarak gerçekleştirir. Her iki
yaklaşımda bütün uygulama sunucularında çalışır.
dil
Muhtemelen Spring AOP nin en çok kullanıldığı alan bildirimsel hareket yönetimidir. Bu yapı
TransactionTemplate soyutlaması üzerine kurulmuştur ve herhangi bir POJO üzerinde
bildirimsel hareket yönetimi sağlayabilir. Hareket stratejisine bağlı olarak kullanılan
mekanizma JTA, JDBC, Hibernate veya hareket yönetimi sağlayan herhangi başka bir API
olabilir.
Spring AOP Spring BeanFactory kavramı ile saydam olarak bütünleşir. Spring BeanFactory
den nesne elde etmeye yarayan kod kendisine advice uygulanıp uygulanmadığını bilmek
zorunda değildir.
Spring AOP’nin Kullanılışı
Burada Spring AOP nin kullanılışı ile ilgili bazı örnekler anlatılacaktır. Bunlar tracing ve
m
logging aspect örnekleri, aspect oriented’ın Hello World’ü, Spring framework’ün sağladığı
yetenekleri kullanarak aspect leri uygulamak amacıyla pointcut ve advice lar tanımlama ve
Spring de gerçekleştirimi yapılan aşağıdaki AOP kavramlarının nasıl kullanıldığıdır.
• Advice: before, afterReturning ve afterThrowing advice ları bean ler olarak
nasıl tanımlanır.
o
• Pointcuts: her şeyi XML Spring Bean konfigürasyon kütüğünde beraber bağlayabilmek
için durağan pointcut mantığı nasıl tanımlanır.
• Advisors: pointcut tanımlarını advice beanleri ile ilişkilendirmek için bir yol.
i.c
İlk adımda basit bir java uygulaması oluşturacağız. IIsMantigi ara yüzü ve onu
gerçekleştiren bir IsMantigi sınıfı oluşturacağız.
}
}
dil
public class IsMantigi implements IIsMantigi {
public void is () {
System.out.println(“IsMantigi.is()’in icindeyiz”);
va
Ve IsMantigi bean’inin genel yöntemini kullanacak bir AnaUygulama yazılabilir.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
//bir nesne al
w.
m
<!-- Bean konfigürasyonu -->
<bean id="ismantigibean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>IIsMantigi</value>
o
</property>
<property name="target">
<ref local="beanTarget"/>
i.c
</property>
</bean>
<!-- Bean Siniflari -->
<bean id="beanTarget"
class="IsMantigi"/>
</beans>
bağlandı. dil
Bu konfigürasyon kütüğü ,“springconfig.xml” olarak kaydedildi, yüklenecek bean’in ara
yüzünü IIsMantigi olarak eşlendi. Sonrada bean IsMantigi gerçekleştirim sınıfına
• Spring.jar
• aopalliance.jar
• commons-logging.jar
• jakarta-oro.jar
ja
nesnem:Sinifim ctx:ApplicationContext
w.
getBean(String)
create
testNesne:IsMantigi
void is()
ww
m
Tracing aspect hedef bir uygulama içinde izlenilen yöntemleri çağırmayı ve yöntemlerden
dönmeyi ele alır ve elde ettiği bilgiyi bir yolla gösterir. Bu türdeki birleşme noktalarını (join
points) ele almak için before ve after advice türleri kullanılır. Bu advice lar yöntemlerin
bu birleşme noktalarından önce veya sonra tetiklenirler. Spring framework kullanılarak
Method Tracing aspect için before advice TracingBeforeAdvice sınıfında
o
tanımlanmıştır.
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
i.c
public class TracingBeforeAdvice implements MethodBeforeAdvice {
public void before (Method m, Object[] args, Object
target) throws Throwable {
System.out.println(“Hello world! (by ” +
this.getClass().getName() + “)”);
dil
}
}
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
va
public class TracingAfterAdvice implements AfterReturningAdvice {
this.getClass().getName() + ")");
}
}
Her iki sınıfta Spring framework ünden uygun advice ara yüzlerinin gerçekleştirimini yaparak
w.
advice ın özel bir parçasını temsil ediyor. Her iki advice türü de Spring’in çalışma zamanında
uygun birleşme noktalarına ulaşıldığında advice ları bildirebilmesini etkin kılmak için hem
before(..) hemde afterReturning(..) yöntemlerinin gerçekleştiriminin yapıldığını
belirtir. TracingAfterAdvice sınıfının AfterReturningAdvice sınıfının
gerçekleştirimini yapması aslında hiçbir şey ifade etmez bunun anlamı advice ın sadece
birleşme noktasına istenmeyen durum oluşmadan ulaşılırsa çalışabileceğidir.
ww
m
<beans>
<bean id="ismantigibean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>IIsMantigi</value>
o
</property>
<property name="target">
<ref local="beanTarget"/>
i.c
</property>
<property name="interceptorNames">
<list>
<value>theTracingBeforeAdvisor</value>
<value>theTracingAfterAdvisor</value>
</list>
dil
</property>
</bean>
<!-- Bean Siniflari -->
<bean id="beanTarget" class="IsMantigi"/>
<value>.*</value>
</property>
</bean>
w.
</property>
<property name="pattern">
<value>.*</value>
</property>
</bean>
<!-- Advice siniflari -->
<bean id="theTracingBeforeAdvice"
m
class="TracingBeforeAdvice"/>
<bean id="theTracingAfterAdvice"
class="TracingAfterAdvice"/>
</beans>
o
theTracingBeforeAdvisor ve theTracingAfterAdvisor advisor ları daha önce
tanımlanan ismantigibean’ine eklendi. Her advisor bean üzerinde ilişkilendirildikleri
birleşme noktalarını kesecektir. Advisor lar bean lerin kendileridir ve bunların işi poincut
i.c
tanımlarını ve advice beanlerini bir arada bağlamaktır. Bu örnekteki pointcut tanımları
düzgün ifadelerdir. Bu ifadeler genel ara yüz IIsMantigi ara yüzündeki birleşme
noktalarını belirlemek için kullanılmıştır. IIsMantigi ara yüzü üzerinde farklı birleşme
noktaları kümesi tanımlamak için kullanılabilecek bazı düzgün ifade örnekleri aşağıdaki
gibidir.
getBean(String)
create
ja
testNesne:IsMantigi
void is()
w.
Şekil 5 - Ardıl Etkileşim çizeneği IsMantigi bean ine uygulanan Method Tracing
aspect’i gösteriyor.
m
Method Tracing aspect daha karmaşık olan Logging aspect elde etmek için genişletilebilir.
Logging aspect tekrar kullanmaya iyi bir örnektir. Uygulamamız içinde Logging aspect i
kullanabilmek için birkaç değişiklik yapmak gerekiyor ve bir istenmeyen durum sınıfı
oluşturuyoruz. IsMantigiIstenmeyenDurum sınıfı IIsMantigi ara yüzündeki yeni
o
method void is2() den ve IsMantigi gerçekleştirim sınıfından fırlatabileceğimiz bir
istenmeyen durum sağlıyor.
i.c
extends Exception
{
dil
{
public void is();
"IsMantigi.is() in icinde");
}
{
System.out.println(
"IsMantigi.is2() nin icinde");
throw new IsMantigiIstenmeyenDurum();
}
}
ww
import org.springframeworkcontext.ApplicationContext;
import
org.springframework.context.support.FileSystemXmlApplicationConte
m
xt;
o
{
// Read the configuration file
ApplicationContext ctx =
i.c
new FileSystemXmlApplicationContext(
"springconfig.xml");
testNesne.is();
try
{
dil
//bean’in genel yöntemlerini çalıştır.
va
testNesne.is2();
}
catch(IsMantigiIstenmeyenDurum imid)
{
System.out.println(
"IsMantigiIstenmeyenDurum yakalandi");
}
ja
}
}
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
m
Son adım olarak springconfig.xml konfigürasyon kütüğünü değiştirmek kalıyor.
AnaUygulama sınıfını çalıştırınca alacağımız çıktı aşağıdaki gibi olacaktır:
o
Hello world! (by TracingBeforeAdvice)
IsMantigi icindeyiz.
Hello world! (by TracingAfterAdvice)
Spring loglama bilgileri…
i.c
Hello world! (by TracingBeforeAdvice)
IsMantigi.is2() nin icinde
Spring loglama bilgileri…
Logging that a IsMantigiIstenmeyenDurumException was thrown.
IsMantigiIstenmeyenDurum yakalandi
nesnem:Sinifim ctx:ApplicationContext
getBean(String)
create
dil
testNesne:IsMantigi
advice1 : T racingBeforeAdvice advice2 : T racingAfterAdvice advice3 : LoggingT hrowsAdvice
va
void before(Method, Object[], Object)
void is()
void is2()
Şekil 6 - Logging advice ının IsMantigi bean ine uygulanmasını gösteren ardıl etkileşim
çizeneği.
Logging aspect etkili bir biçimde var olan aspect leri parçalarını nasıl yeniden
ww
Burada Spring AOP nin basit bir biçimde nasıl kullanılabileceğini anlatmaya çalıştım.Bu
makale ve ilgili örnekler www.onjava.com sitesinde ki Russell Miles a ait ‘An Introduction to
Aspect-Oriented Programming with Spring Framework, Part 1’ adlı makaleden çevrilmiştir.
KAYNAKÇA
m
• www.javaworld.com
• www.onjava.com
o
i.c
dil
ja va
w.
ww