ProgramlamaJava mimarı

Proxy nedir, Java'da proxy türleri nelerdir ve bununla nesnelerin dinamik davranışları nasıl gerçekleştirilir?

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

Cevap.

Soru geçmişi:

Proxy nesneleri ve Proxy deseni Java'da, gerçek bir nesneye erişimi kontrol edebilen, davranışını değiştirebilen veya kesişen işlevleri (güvenlik, günlüğe kaydetme, metrikler) enjekte edebilen yer tutucu nesneleri oluşturmak için ortaya çıktı. Java 1.3'ten itibaren, java.lang.reflect paketinde standart dinamik proxy'ler için destek eklendi ve sonrasında CGLIB ve ByteBuddy gibi popüler kütüphaneler geliştirildi.

Problem:

Mevcut bir sınıfın mantığını doğrudan değiştirmek her zaman mümkün veya pratik değildir. Sıklıkla, mevcut nesnenin kaynak kodunu değiştirmeden şeffaf bir şekilde davranış eklemek (örneğin, günlüğe kaydetme, önbellekleme, işlemler) gerekmektedir. Bu, standart kalıtım araçları ile mümkün değildir.

Çözüm:

Proxy nesneleri, statik (manuel alt sınıflama ile) veya dinamik (yansıma veya bayt kodu mekanizması ile) olarak uygulanabilir. Dinamik proxy, gerekli arayüzü gerçekleştiren nesneleri anlık olarak oluşturmaya olanak tanır ve çağrıları gerçek nesneye invoke() metodu içinde devreder, bu da üçüncü taraf davranışlarını enjekte etmek için esneklik sağlar.

Kod örneği:

import java.lang.reflect.*; interface Service { void doWork(); } class RealService implements Service { public void doWork() { System.out.println("Çalışmayı yapıyorum!"); } } class LoggingInvocationHandler implements InvocationHandler { private final Object target; public LoggingInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Çağrılıyor: " + method.getName()); return method.invoke(target, args); } } Service real = new RealService(); Service proxy = (Service) Proxy.newProxyInstance( real.getClass().getClassLoader(), new Class[] {Service.class}, new LoggingInvocationHandler(real)); proxy.doWork(); // Günlük kaydı çağrılıyor

Anahtar özellikler:

  • Statik proxy'ler her işlev için önceden tanımlanmış koda ihtiyaç duyar
  • Dinamik proxy'ler herhangi bir arayüz için çalışma zamanında anlık olarak oluşturulabilir
  • Arayüzü olmayan sınıflar için üçüncü taraf kütüphaneler (örneğin, CGLIB) gerekmektedir.

Soru kapamaları.

Java'daki standart dinamik Proxy, arayüz uygulamayan sınıflar ile çalışabilir mi?

Hayır. Java'daki standart Proxy yalnızca arayüzlerle çalışır. Arayüzü olmayan sınıflar için (örneğin, sıradan bir sınıfı proxy'lemek istiyorsanız) üçüncü taraf araçlara (örneğin, CGLIB, ByteBuddy) ihtiyaç vardır.

Özel yöntemleri olan bir arayüz için proxy oluşturulabilir mi?

Hayır. Java'daki arayüzler, proxy'lenmesi gereken özel yöntemleri içeremez. Dinamik proxy, arayüzün genel yöntemlerini uygular. Java 9'dan itibaren özel varsayılan yöntemler eklendi, ancak bunlar proxy üzerinden erişilemez.

InvocationHandler ile MethodInterceptor (CGLIB) arasındaki fark nedir?

InvocationHandler, dinamik proxy'ler için kullanılan standart JDK arayüzüdür. Arayüzün yöntem çağrılarını kabul eder. MethodInterceptor, dinamik kalıtım yoluyla herhangi bir sınıfta yöntem çağrılarını yakalayan CGLIB arayüzüdür. Uygulama ve seviye açısından fark: JDK yalnızca arayüzlerle çalışır, CGLIB ise herhangi bir sınıfla çalışır.

Sık yapılan hatalar ve anti-patentler

  • Hata türü: Proxy'yi arayüz uygulamayan bir sınıf için kullanmaya çalışmak
  • Gizli döngüsel çağrılar, StackOverflow'a yol açar
  • Proxy'leşmeye uygun olmayan sınıfların proxy'lenmesi veya final sınıfları proxy'lemeye çalışmak

Gerçek hayat örneği

Olumsuz durum

Mühendis, tüm hizmetlerdeki her yöntemde günlüğe alma kodunu manuel olarak tekrarlar. Yeni yöntemler eklendiğinde mantığı sürekli tekrarlar, genellikle gerekli çağrıları eklemeyi unutur.

Artıları:

  • Şeffaf, yürütme akışını anlamak kolay

Eksileri:

  • Zaman kaybı, birçok benzer kod, bakım zor

Olumlu durum

Projeye, dinamik proxy üzerinden AOP entegre edilmiştir: günlüğe alma ve işlem kontrolü merkezi olarak gerçekleştirilen yer tutucu sarfiyatları ile gerçekleştirilir.

Artıları:

  • Herhangi bir kesişen işlevselliği daha hızlı entegre etme ve değiştirme, tekrar yok

Eksileri:

  • Proxy'nin nasıl çalıştığını anlamak gerekliliği, hata ayıklamada potansiyel zorluklar