Soru Geçmişi:
Dynamic Proxy Pattern, Java 1.3'te ortaya çıktı ve AOP, günlük kaydı, güvenlik, dinamik kod üretimi gibi kalıpları uygulamayı mümkün kıldı, elle proxy sınıfları yazmadan. Bu, Spring, Hibernate ve diğer çerçevelerde oldukça popüler hale geldi.
Sorun:
Bazen mevcut bir arayüze işlevsellik eklemek veya çalışırken yöntemlerin davranışını değiştirmek gerekebilir, bunu kaynak kodunu değiştirmeden yapmak. Örneğin: her yöntem çağrısının kaydedilmesi, erişim kontrolü, profil oluşturma. Ana sorun, özellikle çok sayıda sınıf olduğunda veya sınıflar dinamik olarak oluşturulduğunda, bunu tüm sınıflar için "elle" yapmanın imkansızlığıdır.
Çözüm:
Java, java.lang.reflect paketinde herhangi bir arayüz için "anlık" proxy nesneleri oluşturmak amacıyla Proxy.newProxyInstance ile standart bir API sağlar. Her yöntem çağrısını alan ve kendi mantığını uygulayan bir InvocationHandler nesnesi gerçekleştirilir.
Kod Örneği:
import java.lang.reflect.*; interface Service { void serve(); } class ServiceImpl implements Service { public void serve() { System.out.println("Serving..."); } } class LoggingHandler implements InvocationHandler { private final Object target; public LoggingHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Calling " + method.getName()); return method.invoke(target, args); } } Service service = (Service) Proxy.newProxyInstance( Service.class.getClassLoader(), new Class[]{Service.class}, new LoggingHandler(new ServiceImpl())); service.serve();
Temel Özellikler:
Standart dynamic proxy ile normal bir sınıfı, arayüzleri olmayan bir sınıfı "sarmak" mümkün mü?
Hayır. Dynamic Proxy yalnızca arayüzlerle çalışır. Sınıflar için bytecode manipulation (örneğin, CGLIB) gereklidir.
Eğer arayüz, InvocationHandler'dan dönen değerle uyumsuz bir dönüş türüne sahip yöntemler içeriyorsa ne olur?
ClassCastException fırlatılacaktır, bu nedenle dönüş değeri arayüz tanımı ile kesinlikle uyumlu olmalıdır.
Final yöntemler için dynamic proxy kullanılabilir mi?
Hayır. Proxy yalnızca arayüz düzeyinde çalışır ve orada final yöntem yoktur. Final yöntemler hiç bir şekilde geçersiz kılınamaz.
Olumsuz Durum
Geliştirici, arayüzü olmayan sınıflara Proxy üzerinden audit günlüğü eklemeye çalıştı.
Artıları:
Eksileri:
Olumlu Durum
Bir arayüz olarak sözleşme belirlendi, buna uygun bir proxy sarmalayıcı yapıldı.
Artıları:
Eksileri: