Download as pdf
Download as pdf
You are on page 1of 33

o m

CEPHEYE YÖNELİK PROGRAMLAMA

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.

Cepheye-yönelik programlama (AOP) enine kesen ilgilerin modüle edilmesini sağlayarak


ilgileri önceki yöntemlerden daha iyi ayırır.
va
Bu makalede ilk önce enine kesen ilgilerin herhangi karmaşık bir yazılım sisteminde neden
oldukları problemler açıklanacak. Sonra AOP çekirdek kavramları açıklanacak ve AOP nin
enine kesen ilgiler ile ilgili problemleri nasıl çözdüğü gösterilecektir.

Yazılım programlama yöntemlerinin evrimi


Bilgisayar bilimlerinin ilk günlerinde, geliştiriciler direk makine-düzeyi kodlama ile program
ja

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

yöntem problemlerimizi ayrıştırabileceğimiz yeni yollar gösterir: makine kodları, makine-


bağımsız kodlar, yordamlar, sınıflar vb. Her yeni yöntem sistem gereksinimlerinden
programlama yapılarına daha doğal bir eşleme sağlar. Bu yöntemlerin evrimleşmesi bizim
yükselen karmaşıklıklarda sistemler üretmemizi sağladı. Bu gerçeğin tersi de eşit olarak
doğru olabilir; bizim karmaşıklığı daha çok sistemler oluşturmamıza izin verildi çünkü bu
teknikler bizim bunu yapmamıza, kendileri bu karmaşıkların üstesinden gelerek, izin verdi.
Günümüzde, NYP bir çok yeni yazılım projesi için seçilen yöntem olarak hizmet vermektedir.
NYP ortak davranışları modellemek için geldiğinde gücünü göstermişti. Ancak kısaca

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 1. İlgilerin bir kümesi olarak gerçekleştirim modülleri

Ş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

Bir sistemdeki enine kesen ilgiler

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:

public class İşSınıfı extends BaşkaİşSınıfı {


ja

// çekirdek veri elemanları

// diğer veri elemanları : Log stream, veri-tutarlılık bayrağı

// taban sınıfın yöntemlerini yeniden yaz


w.

public void birİşYap (İşBilgisi bilgi) {


// yetkiden emin ol

// verinin gereken bilgiyi taşıdığından emin ol

// diğer işletim dizileri eriştiğinde verinin tutarlı


ww

// kalmasını sağlamak için nesneyi kitle

// ön belleğin açık olduğundan emin ol

// işlemin başlangıcını logla

// ==== Çekirdek işlemleri yap ====


// işlemin bittiğini logla

m
// nesnedeki kilidi aç
}
// yukarıdakine benzer diğer işlemler

public void kayıtEt (KalıcıDepo kd) {

o
}

public void yükle (KalıcıDepo kd) {


}

i.c
}
}

Yukarıdaki kodda en az üç mesele üzerinde düşünmeliyiz. Birincisi, diğer veri üyeleri


bu sınıfın çekirdek ilgilerine ait değildir. İkincisi, birİşYap() yönteminin gerçekleştirimi
sadece çekirdek işlemleri yapmıyor bu yöntemde ayrıca loglama, yetki kontrolü, çoklu işletim
dizisi emniyeti, verinin taşıdığı bilgiyi geçerleme ve ön bellek yönetim ilgilerinin

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.

Enine kesen ilgiler problemi


Enine kesen ilgiler bir çok modül üzerine dağılmalarına rağmen, mevcut gerçekleştirim
teknikleri bu gereksinimleri tek-boyutlu yöntemler, gereksinimlerin gerçekleştirim
va
eşlemelerini tek boyut boyunca zorlama, kullanarak gerçekleştirmek eğilimindedir. Bu tek
boyut çekirdek-düzeyi gerçekleştirim olma eğilimindedir. Geri kalan gereksinimler bu baskın
boyutta etiketlenirler. Diğer bir deyişle, gereksinim uzayı n-boyutlu bir uzay, oysa
gerçekleştirim uzayı tek-boyutludur. Bu, uygunsuz gereksinim-gerçekleştirim eşlemesindeki
uyuşmayan sonuçlara benziyor.

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.

kalabalığı her ilginin gerçekleştiriminden bir elemanın varlığının eş anlı bulunması


demektir buda kod karıştırma olarak sonuçlanır.
• Kod dağıtma : Enine kesen ilgiler bir çok modül üzerine dağıldıkları için, ilgili
gerçekleştirimleri de bu modüller üzerinde dağılırlar. Örneğin, veritabanı kullanan bir
sistemde, performans ilgisi veritabanına erişen bütün modülleri etkileyebilir.
ww

Saklı olan anlamlar


Kod karıştırma ve dağıtmanın ikisi birlikte bir yazılım sisteminin tasarımını ve geliştirilmesini
bir çok yönden etkiler:

• Zayıf izlenebilirlik: Bir çok ilgiyi eş anlı gerçekleştirmek ilgi ve gerçekleştirimi


arasındaki benzerliği kapatır ve bu ikisi arasında eşleme yapmak zorlaşır.
• Daha düşük üretkenlik: Bir çok ilgiyi aynı anda gerçekleştirmek geliştiricinin
dikkatini ana ilgiden daha önemsiz olan ilgilere doğru kaydırır ve bu da daha düşük

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.

Visitor ve Template Method gibi davranışsal örüntüler gerçekleştirimi ertelememizi sağlar.


Ancak mix-in deki durum gibi işlemin kontrolü – visiting mantığını veya template
yöntemlerini uyandırmak – yine ana sınıflarda kalır.
ja

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.

gibi deployment a özgü sorunlara odaklanırken bean geliştiricileri iş mantığı üzerinde


odaklanırlar. Bean geliştiricileri kalıcılık katmanındaki bir çok parça için depolamaya özgü
niteliklerin farkında olarak bir şey yapmaz, bu durumda kalıcılık enine kesen ilgilerinin
gerçekleştirimi XML tabanlı tanımlama kütükleri kullanılarak yapılır.

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.

AOP nin Temelleri

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

AOP de üç ayrık geliştirme adımı vardır:

1. Aspectual ayrıştırma: Gereksinimleri enine kesen ilgiler ve genel ilgiler olarak


tanımlayabilmek için ayrıştırma. Modul-düzeyi ilgileri sistem-düzeyi enine kesen
w.

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

belirler. Yeniden birleştirme işlemi, ayrıca örme(weaving) veya bütünleştirme olarak


da bilinir, son sistemi birleştirmek için bu yeniden birleştirme kuralları bilgisini
kullanır. Kredi kartı işleme örneği için, AOP gerçekleştirimi tarafından sağlanan bir
dille, her işlemin başlangıcının ve tamamlanışının loglanmasını belirtebiliriz. Ayrıca her
işlemin iş mantığı ile çalışmadan önce yetki kontrolünü temizlemesini belirtebiliriz.
o m
i.c
Şekil 3. AOP geliştirme aşamaları

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.

Aşağıdaki kredi kartı işleme modülünü düşünelim:


w.

public class KrediKartıİşleyicisi {


public void borç(KrediKartı kart, Birim miktar)
throws GeçersizKartHatası, YetersizBakiyeHatası,
KartZamanAşımınaUğramışHatası {
// Borç verme mantığı }
ww

public void kredi(KrediKartı kart, Birim miktar)


throws GeçersizKartHatası {
// Kredi mantığı
}
}
Ayrıca aşağıdaki loglama ara yüzünü düşünelim:

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:

public class LoglamalıKrediKartıİşleyicisi {


Loglayıcı _loglayıcı;

public void borç(KrediKartı kart, Para miktar)

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);
}

public void Kredi(KrediKartı kart, Para miktar)


throws GeçersizKartHatası {
ja

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

AOP dillerinin anatomisi


Bütün diğer programlama yöntemleri gerçekleştirimleri gibi, bir AOP gerçekleştirimi de iki
parçadan oluşur: bir dil belirtimi ve bir gerçekleştirim. Dil belirtimi dilin yapısını ve söz
dizimini tanımlar. Dil gerçekleştirimi dil belirtimine göre kodun doğruluğuna bakar ve onu
hedef makine’nin çalıştırabileceği biçime çevirir. Bu bölümde bir AOP dilinin bölümleri ve
parçaları açıklanacaktır.

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.

AOP dil gerçekleştirimi


AOP dili derleyicileri iki mantıksal adımı yerine getirirler:

1. Ayrık ilgileri birleştir

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

AOP nin faydaları


AOP, kod karıştırmanın ve kod dağıtmanın neden olduğu daha önce bahsedilen problemlerin
üstesinden gelmemize yardım eder. AOP nin bize sağladığı bazı özel faydalarda şunlardır:
w.

• Enine kesen ilgilerin modularize gerçekleştirimi: AOP her ilgiyi minimum


bağımlılıkla ayrı olarak ele alır ve bu enine kesen ilgilerin varlığına rağmen modularize
olan bir gerçekleştirimle sonuçlanır. Bu gerçekleştirim en az bağımlı kodla bir sistemi
üreten bir gerçekleştirimdir. Her ilginin gerçekleştiriminin ayrı olması kod
düzensizliğini azaltmaya yardım eder. Ayrıca bir sistemin modularize
gerçekleştirilmesi sistemin anlaşılabilirliğini ve güncellenmesini kolaylaştırır.
• Zamanla geliştirmesi kolay sistemler: Aspected modüller enine kesen ilgilerin
ww

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.

public aspect LogKrediKartıİşleyicisiİşlemleri {


Loglayıcı loglayıcı = new StdÇıktıLoglayıcı();

pointcut publicOperation():
ja

execution(public * KrediKartıİşleyicisi.*(..));

pointcut publicOperationCardAmountArgs(KrediKartı kart,


Para miktar):
w.

publicOperation() && args(kart, miktar);

before(KrediKartı kart, Para miktar):


publicOperationCardAmountArgs(kart, miktar) {
logOperation("Başlama",
thisjoin point.getSignature().toString(), kart,
ww

miktar);
}

after(KrediKartı kart, Para miktar) returning:


publicOperationCardAmountArgs(kart, miktar) {
logOperation("Tamamlanma",
thisjoin point.getSignature().toString(), kart,
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);
}
}

AOP ye ihtiyacım varmı?

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.

AOP nizi alın!


Bu makalede enine kesen ilgiler ile ilgili problemleri, onları gerçekleştirmek için var olan
ja

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.

Bu makale www.javaworld.com adresindeki Ramnivas Laddad a ait “I want my AOP!, Part 1


Separate software concerns with aspect-oriented programming” adlı makaleden cevrilmiştir.
ww
İkinci-nesil aspect oriented programming

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

AspecJ ile eski AOP


AOP orta katmandaki bir framework te şöyle kullanılabilir: Framework ümüzdeki hizmetlere
istemcinin bir proxy aracılığıyla eriştiğini düşünelim. Hizmet bir başka SM(Sanal Makine)
üzerinde olabilir ve her hangi bir remoting teknolojisi ile erişilebilir; bunları istemciden
saklamak framework ün var olma nedeni. Framework ümüzün özelliklerinden bir tanesi bir
geliştiricinin istemciden, istemciye saydam olarak çağırılan hizmete istediği her hangi bir
bağlamı hazırlayabilme yeteneğidir. Örneğin, bir uygulama bir kullanıcıyı güvenlik hizmeti
içerisine loglayabilir ve bağlam içine bir yetki kontrolü söz dizimi koyabilir. Bundan sonra, bu
uygulama tarafında çağrılan her hizmet yetki kontrolü söz dizimini bağlamdan – sunucu
tarafında – alabilir ve onu istemcinin ulaştığı işlevselliği kontrol etmek için kullanabilir.

m
Öncelikle bağlamın hazırlandığını göstermek için basit bir test yazalım:

public class BağlamGeçişTest extends TestCase {


public void test() {

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.

Şimdi testimizin kullandığı sınıflara bakalım. İstemciTaraflıBağlam bir HashMap


çevresinde basit bir singleton sarmalayıcıdır, yani bağlamın ona ihtiyaç oluncaya kadar
w.

saklandığı yerdir:

public class İstemciTaraflıBağlam {


private static final İstemciTaraflıBağlam VARLIK = new
İstemciTaraflıBağlam();
ww

pulic static İstemciTaraflıBağlam varlık() {


return VARLIK;
}

private final Map mBağlam = new HashMap();

public void yerleştir (Object anahtar, Object değer) {


mBağlam.put(anahtar, değer);
}

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);
}
}

public class SunucuTaraflıBağlam { dil


BağlamAlıcıGerc SunucuTaraflıBağlam ın tek bir varlığını döndürüyor, bu
İstemciTaraflıBağlam ın yaptığına benzer fakat sunucu tarafında kullanılıyor:

private static final SunucuTaraflıBağlam VARLIK = new


SunucuTaraflıBağlam();
va
public static SunucuTaraflıBağlam varlık() {
return VARLIK;
}

private final Map mBağlam = new HashMap();


ja

public void bağlamKur(Map bağlam) {


mBağlam.putAll(bağlam);
}

public Object al(Object anahtar) {


w.

return mBağlam.get(anahtar);
}
}

Peki bağlam istemciden sunucuya nasıl alınacak? Aşağıdaki aspect ile:


ww

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.

Bağlam-geçirme işlevselliğini bir aspect de yazmak bize geleneksel nesneye-dayalı tasarımın

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

Bir AOP istek listesi dil


biçimde çalışacaktır. Bu tam olarak AOP nin sağlamaya çalıştığı modularizasyonun
sıralanışıdır.

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

Bunun yerine biz BağlamAlıcıGerc in advice ların uygulandığı ve uygulanmadığı


varlıklarını isteyebilmeliyiz. Örneğin bir nesne ile ilişkilendirilen bir advice belleği ve diğer
kaynaları aşrı biçimde tüketiyor o zaman muhtemelen ön bellekte duran ve kullanılmayan
varlıklara bu advice ın uygulanmasını istemeyiz. Bayt dizileri haline çevirilemeyen
(unserializable) nesnelere referanslar içeren advice normalde bayt dizileri haline çevirilebilen
bir nesneyi çeviremememize neden olabilir. AspectJ şuanda bir sınıfın sadece bazı varlıklarını
advice edebilmemize izin vermiyor. Bu çerçevece yapılan çalışmalar var ama sorun direk
olarak ele alınsa daha hoş olacak.
Son olarak başka bir esneklik istiyoruz: derlenmiş bir programa aspect ler ekleyebilmekten

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.

JBoss AOP ile Devingen AOP


JBoss AOP JBoss tarafından geliştirilen bir AOP gerçekleştirimidir. JBoss AOP JBoss uygulama
w.

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:

public class BağlamGecici implements Interceptor {


ww

public String getName() {


return getClass().getName();
}

public Object invoke(Invocation invocation) throws Throwable {


SunucuTaraflıBağlam.varlık().bağlamKur(
İstemciTaraflıBağlam.varlık().bağlamAl());
return invocation.invokeNext();
}

m
}

JBoss AOP advice org.jboss.aop.Interceptor ara yüzünü gerçekleştiren basit bir


Java sınıfıdır. Bu ara yüzde bir tane sıradan yöntem: getName() ve bir tane ilginç yöntem:
invoke(Invocation) var. invoke(Invocation) yöntemine AspectJ advice ında

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.

public class ProxyFactory {


ww

private static final ProxyFactory VARLIK = new ProxyFactory();

public static ProxyFactory varlık() {


return VARLIK;
}

public Object getProxy(String ad) {


Advised advised = (Advised) new BağlamAlıcıGerc();
advised._getInstanceAdvisor().insertInterceptor(new

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:

public class BağlamAlıcıGerc implements BağlamAlıcı {


/** @@contextual */
public Object al(Object anahtar) {
va
return SunucuTaraflıBağlam.valık().al(anahtar);
}
}

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

Özellik AspectJ AspectWerkz JBoss AOP Spring dynaaop

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ı

Saydamlık(Transparency) Saydam Saydam Seçim Fabrika Fabrika

Varlık başına aspect Hayır Hayır Evet Evet Evet

Yapıcı, alan, fırlatma ve


Hepsi Hepsi Bazıları Bazıları Hiçbiri

dil
cflow interception ları

Notlar(Annotations) Hayır Evet Evet Evet Hayır

Tek başına(Standalone) Evet Evet Evet Hayır Evet

AOP Alliance Hayır Hayır Hayır Evet Evet

Bağlantı(Affiliation) IBM BEA JBoss Spring ?


va
Framework ler ağırlıklarına göre sıralanmıştır. En soldaki AspectJ kendine ait dil ve
destekleyici araçlar, Java kodları ve ve aspect ler arasında katı bir ayırım ve durağan
derleme ile en ağır AOP gerçekleştirimi oluyor. Sağdakiler ise istemci koduna daha fazla etki
ilede olsa her şeyi çalışma zamanında yapan daha hafif frameworkler. Aslında Java’nın
devingen proxylerini de basit bir AOP framework olarak düşünebiliriz bunuda belki tablonun
sağ taraflarında bir yerlere yerleştirebiliriz.
ja

“Saydamlık” framework ün istemci kodunda değişikliğe ihtiyac duymadanmı (“saydam”)


yoksa advice uygulanan nesneleri bir fabrikadan elde etmek için bir istemciye gereksinim
duyarakmı (“fabrika”) çalıştığını gösteriyor. JBoss AOP bu iki teknik arasında bir seçim
yapabilmemize izin veriyor. “Varlık başına aspect” i destekleyen framework ler advice ın
advice uygulanan sınıfın seçtiğimiz bir varlığı ile ilişkilendirilebilmesine izin veriyor. Bu
w.

AspectJ ve AspectWerkz’ in yapabildiği farklı aspect kümesi durumlarını advice uygulanan


her varlıkla ilişkilendirebilmekten farklıdır. Ayrıca varlık başına aspect kullanmak fabrika
kullanmayı gerekli kılar.

“Yapıcı, alan, fırlatma ve cflow interception” framework ün yöntemlerden başka program


yapılarına da advice uygulayıp uygulayamadığını gösteriyor. Bu AOP framework lerinin
tamamı giriş veya mixin leri destekler, bu burada değinmediğimiz önemli bir AOP özelliğidir.
ww

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.

Bu makale www.javaworld.com adresindeki Dave Schweisguth a ait “Second-generation


va
aspect-oriented programming, Apply advice dynamically with the new crop of AOP
frameworks ” adlı makaleden cevrilmiştir.
ja
w.
ww
Spring AOP (Aspect Oriented Programming)

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.

Spring’in anahtar bileşenlerinden biride AOP framework ü. Spring’in IoC (Inversion of


Control) kabları (BeanFactory ve ApplicationContext) AOP ye bağlı değildir yani AOP yi
kullanmak zorunda değilsiniz istemiyorsanız kullanmazsınız ama AOP Spring’in IoC sini
tamamlayarak çok yetenekli bir orta katman çözümünün ortaya çıkmasını sağlar. Amaç en
iyi AOP gerçekleştirimini sağlamak değildir (Spring AOP’nin epey yetenekli olmasına

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.

AOP Spring de aşağıdaki sebeplerden dolayı kullanılır:

• 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.

• Aspect: İlginin ne olduğunu daha önce açıklamıştım. AOP de modüllere ayırma


birimine verilen ad aspect tir, bu genel bir ilginin gerçekleştiriminin NYP de sınıf adını
almasına benzer. Aspectlerin gerçekleştirimi Spring kullanılarak Advisor veya
interceptor lar olarak yapılır.
• Birleşme noktası (Joinpoint): Programın çalıştığı süreç boyunca yöntemlerin
çalıştırıldığı veya özel istenmeyen durumların fırlatıldığı noktalar. Spring AOP de bir
birleşme noktası her zaman yöntem çağırmadır.
ww

• 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’in bildirimsel hareket yönetimi aşağıdaki farklarla EJB CMT ‘ e benzer.


va
• Hareket yönetimi herhangi bir POJO ya uygulanabilir. Spring iş nesnelerinin ara yüzleri
gerçekleştirmesini tavsiye eder ama bu sadece iyi bir programlama pratiğidir ve
framework tarafından zorlanmaz.
• Spring hareket API si kullanılarak hareketsel bir POJO içinde programsal geri sarmalar
(programmatic rollback) yapılabilir. Spring bunun için ThreadLocal değişkenlerini
kullanarak statik yöntemler sağlar böylece geri sarma garanti etmek için EJB Context
ja

gibi bağlam nesneleri hazırlamak zorunda kalmayız.


• Geri Sarma kuralları tanımlanabilir. EJB uygulamada oluşan ve yakalanamayan bir
istenmeyen durumda otomatik olarak hareketin geri alamaz ve uygulama geliştiriciler
genellikle her istenmeyen durumda hareketi geri almak isterler. Spring hareket
yönetimi hangi istenmeyen durumların ve alt sınıfların otomatik geri sarmaya neden
w.

olması gerektiğini belirlememizi sağlar.


• Hareket yönetimi JTA ya bağımlı değildir, Spring hareket yönetimi değişik hareket
stratejileri ile çalışabilir.

Uygulamaya özel aspect lerin gerçekleştirimini de Spring AOP kullanarak yapabiliriz.


Fakat bu Spring’in bu alandaki yeteneklerinden daha çok bizim AOP kavramlarına
yakınlığımıza bağlı. Bu konuda aşağıdaki gibi başarılı örnekler mevcuttur:
ww

• Özel güvenlik interception ı.


• Geliştirme sürecinde kullanmak için debug ve profil aspectleri.
• Beklenmeyen durumlarda yöneticilere veya kullanıcılara e-posta atan interceptorlar.

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.

Public interface IIsMantigi{


public void is();
}

}
}
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;

public class AnaUygulama {


public static void main (String[] args) {
ja

//konfigürasyon kütügünü oku


ApplicationContext ctx = new
FileSystemXmlApplicationContext(“springconfig.xml”);

//bir nesne al
w.

IIsMantigi testNesne = (IIsMantigi) ctx.getBean(“ismantigibean”);


// public yöntemi calistir.
testNesne.is();
}
}
ww

Spring konfigürasyon bilgileri aşağıdaki gibi bir XML kütüğünde sağlanır.

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

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

Aşağıdaki şekilde AnaUygulama çalıştığı zamanki ardıl etkileşim çizeneği gösteriliyor. Bu


uygulamayı çalıştırabilmek için öncelikle yol (path) ayarları yapmamız gerekecek başta
va
Spring olmak üzere birkaç tane kütüphaneye ihtiyacımız olacak bunlar aşağıdaki .jar uzantılı
kütüklerdir:

• Spring.jar
• aopalliance.jar
• commons-logging.jar
• jakarta-oro.jar
ja

nesnem:Sinifim ctx:ApplicationContext
w.

getBean(String)
create
testNesne:IsMantigi

void is()
ww

Şekil 4 - Ardıl Etkileşim Çizeneği IsMantigi beanini hiçbir aspect uygulanmadığı


zaman gösteriyor
En temel aspect muhtemelen Method Tracing aspect tir, bulabileceğimiz en basit aspect
olduğu için yeni bir AOP yi incelerken başlanması gereken muhtemel en iyi yerdir. Bir Method

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
}
}

Benzer biçimde after advice ı TracingAfterAdvice sınıfında tanımlanabilir.

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
va
public class TracingAfterAdvice implements AfterReturningAdvice {

public void afterReturning(Object object, Method m, Object[]


args,Object target) throws Throwable {
System.out.println("Hello world! (by " +
ja

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

Advice ları uygulamamızda uygun birleşme noktaları ile ilişkilendirebilmek için


springconfig.xml birkaç ekleme yapmak zorundayız. Yeni eklenen kısımlar koyu renkte
görünüyor.

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

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"/>

<!-- before advice icin Advisor pointcut tanimlari -->


<bean id="theTracingBeforeAdvisor"
va
class="org.springframework.aop.support.RegexpMethodPointcutAdviso
r">
<property name="advice">
<ref local="theTracingBeforeAdvice"/>
</property>
<property name="pattern">
ja

<value>.*</value>
</property>
</bean>
w.

<!-- after advice icin Advisor pointcut tanimlari -->


<bean id="theTracingAfterAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdviso
r">
<property name="advice">
<ref local="theTracingAfterAdvice"/>
ww

</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.

• <value>.*</value>: Bu ifade advisor ın ilişkilendirildiği beanler veya bean üzerindeki


bütün birleşme noktalarını seçer.

is()yöntemi üzerindeki birleşme noktalarını seçer.


dil
• <value>./IIsMantigi/.is</value>: Bu ifade IIsMantigi ara yüzü üzerindeki

Bu konfigürasyon ile AnaUygulama yı çalıştırırsak ardıl etkileşim çizeneğimiz


aşağıdaki gibi olur.
va
nesnem:Sinifim ctx:ApplicationContext advice1 : T racingBeforeAdvice advice2 : T racingAfterAdvice

getBean(String)
create
ja

testNesne:IsMantigi

void before(Method, Object[], Object)

void is()
w.

void afterReturning ( Object, Method, Object[], Object)


ww

Şekil 5 - Ardıl Etkileşim çizeneği IsMantigi bean ine uygulanan Method Tracing
aspect’i gösteriyor.

AnaUygulama sınıfının çalıştırdığımız zaman ekrandan alacağımız çıktı aşağıdaki gibi


olacaktır.

Hello world! (by TracingBeforeAdvice)


IsMantigi icindeyiz.
Hello world! (by TracingAfterAdvice)

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.

public class IsMantigiIstenmeyenDurum

i.c
extends Exception
{

public interface IIsMantigi

dil
{
public void is();

public void is2()


throws IsMantigiIstenmeyenDurum;
}
va
public class IsMantigi
implements IIsMantigi
{
public void is()
{
System.out.println(
ja

"IsMantigi.is() in icinde");
}

public void is2()


throws IsMantigiIstenmeyenDurum
w.

{
System.out.println(
"IsMantigi.is2() nin icinde");
throw new IsMantigiIstenmeyenDurum();
}
}
ww

AnaUygulama sınıfı da void is2() yöntemini de çağırıyor ve potansiyel olarak bu


sınıftan fırlatılan istenmeyen durumları ele alıyor.

import org.springframeworkcontext.ApplicationContext;
import
org.springframework.context.support.FileSystemXmlApplicationConte

m
xt;

public class AnaUygulama


{
public static void main(String [] args)

o
{
// Read the configuration file
ApplicationContext ctx =

i.c
new FileSystemXmlApplicationContext(
"springconfig.xml");

//bir nesne olustur


IIsMantigi testNesne =
(IIsMantigi) ctx.getBean(
"ismantigibean");

testNesne.is();

try
{
dil
//bean’in genel yöntemlerini çalıştır.
va
testNesne.is2();
}
catch(IsMantigiIstenmeyenDurum imid)
{
System.out.println(
"IsMantigiIstenmeyenDurum yakalandi");
}
ja

}
}

LoggingThrowsAdvice sınıfı yeni istenmeyen durum loglaması için advice sağlar.


w.

import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;

public class LoggingThrowsAdvice implements ThrowsAdvice


{
ww

public void afterThrowing(Method method, Object[] args,


Object target, Throwable subclass)
{
System.out.println(
"Logging that a " +
subclass +
"Exception was thrown.");
}
}

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:

Spring loglama bilgileri…..

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

Ve ardıl etkileşim çizeneğimiz de aşağıdaki gibi olacaktır:

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 afterReturning ( Object, Method, Object[], Object)


ja

void before(Method, Object[], Object)

void is2()

void afterT hrowing(Method, Obect[], Object, T hrowable)


w.

Ş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

kullanabileceğimizi ve advice ın throws formumun Spring framework de nasıl kullanılacağını


gösteriyor.

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

You might also like