ProgramlamaBackend geliştirici

Java'daki dynamic proxy mekanizmasının özü nedir, nasıl uygulanır ve hangi amaçlar için kullanılır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

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:

  • Sadece arayüzlerle çalışır
  • Arayüzdeki tüm yöntemler için davranış eklemeyi sağlar
  • AOP, günlük kaydı, işlem kontrolü için kullanılır

Hileli Sorular.

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.

Yaygın Hatalar ve Anti-Patternler

  • Arayüz olmayan sınıflar için dynamic proxy kullanma girişimi
  • InvocationHandler yöntemlerinde tip dönüşü hataları
  • invoke içinde istisnaların başarısız bir şekilde işlenmesi

Gerçek Hayattan Örnek

Olumsuz Durum

Geliştirici, arayüzü olmayan sınıflara Proxy üzerinden audit günlüğü eklemeye çalıştı.

Artıları:

  • Hızlı ve "şeffaf" bir şey yapmaya çalıştı.

Eksileri:

  • Üretim aşamasında bug'lar aldı: proxy, arayüze sahip olmayan normal sınıflarla çalışmadı.
  • Hata ayıklama için zaman kaybı.

Olumlu Durum

Bir arayüz olarak sözleşme belirlendi, buna uygun bir proxy sarmalayıcı yapıldı.

Artıları:

  • Yeni yönlerin (günlük kaydı, güvenlik) eklenmesinde esneklik.
  • Test etme kolaylığı.

Eksileri:

  • Mimariyi biraz yeniden gözden geçirme gerekliliği.