Java reflection proxy sınıfı
Proxyleri kullarak kendi AOP frameworkünüzü oluşturabilirsiniz. İster trace almak, ister performans ölçmek maksatlı olsun, belirli bir classınızın bütün method çağrılarını yakalayabilirsiniz. Hem de bunu classınızı modifiye etmeden, runtime da yaparsınız.
Proxyler loglama amacı ile de kullanılabilir, fakat bütün bir trace’i loglamaktansa sadece loglanması gereken şeyleri loglamak, logların okunabilirliği ve performansı için daha uygun olacaktır.
Java runtime ile gelen Proxy classı sizin parametre olarak vereceğiniz interface’i run time da implement eden bir class generate eder.
Ve aslında runtime da oluşan bu sınıf, basitçe yapılan bütün method callarını sizin vereceğiniz bir InvokeHandler’a yönlendirir. InvokeHandler’ın imzası
public Object invoke(Object proxy, Method method, Object[] args) şeklinde olan bir metodu vardır. Bu metod sizin proxy nesnenize yapacağınız method call’larının düşeceği metoddur.
Örnek
public interface OrderList {
public double calculateSummary();
}
Şeklinde tek metodlu bir interfaceimiz olsun.
Şimdi bu interface’i bir proxy implemantasyon ile sarıp tek metodumuz calculateSummary çağrılarını yakalayalım.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Java reflection.proxy sınıfı örnek kullanımı.
*
* @author selcuk
*
*/
public class AppClient implements InvocationHandler {
/**
*
* Proxy'nin her bir methodu call edildiğinde buraya düşer.<br><hr>
* {@inheritDoc}
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + " called.");
return 1234d;
}
public static void main(String[] args) {
OrderList proxiedOrder = (OrderList) Proxy.newProxyInstance(OrderList.class.getClassLoader(), new Class<?>[] { OrderList.class }, new AppClient());
System.out.println(proxiedOrder.calculateSummary());
}
}
Çalıştırdığımızda
calculateSummary called.
1234.0
çıktısını alırız.
En basit şekli ile Cephe Yönelimli Programlama (Aspect Oriented Programming) temel aldığı yapıya bir örnek vermiş olduk. AOP frameworkleri de proxyler aracılığı ile classlarınızı sararlar ve belirttiğini “advice” ları çalıştırırlar. Advice metod giriş ve/veya çıkışlarında çalıştırılan kodun AOP terminolojisindeki adıdır.
Bundan sonraki aşamada, invoke metodunda OrderList arayüzünün gerçek bir implementasyonunun metodlarını çağırmak gerekecektir.
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println(method.getName() + " begins...");
Object invoke = method.invoke(this.target, args);
System.out.println(method.getName() + " ends...");
return invoke;
}
this.target, InvokeHandler implementasyonumuza constructor’ı aracılığı ile yada bir setter metodu ile sağlanmış olmalıdır.
java.lang.reflect.Proxy’ sınıfının bir kısıtından bahsedilebilir, o da orijinal sınıfınıza proxy almak için mutlaka bir interface kullanmış olmanızdır. Eğer proxy almak istediğiniz class hiç bir sınıfı implement etmiyor ise, bu durumda cglib kullanmanız gerekecektir.
CGLIB http://cglib.sourceforge.net/ adresinden elde edebileceğiniz open source bir kütüphane. Kaba bir tarifle proxy alma işini cglib byte code generate ederek yapiyor. Orijinal classınızdan extend eden bir classı runtimeda generate ediyor.
Kolay gelsin.

