"Merhaba, Amigo."

"Merhaba Rishi."

"Bugün size yeni ve çok ilginç bir konuyu açıklayacağım: dinamik proxy'ler" .

"Java'nın belirli bir sınıfın işlevselliğini değiştirmenin birkaç yolu vardır..."

"İlk yöntem kalıtımdır."

"Bir sınıfın davranışını değiştirmenin en kolay yolu, orijinal (temel) sınıfı miras alan ve onun yöntemlerini geçersiz kılan yeni bir sınıf oluşturmaktır. Ardından, orijinal sınıfı kullanmak yerine türetilmiş sınıfı kullanırsınız. Örneğin:"

Reader reader = new UserCustomReader();

"İkinci yöntem, bir sarmalayıcı sınıfı kullanmaktır."

" BufferedReader bu sınıf tipine bir örnektir. Birincisi, Reader'ı miras alır . Diğer bir deyişle, Reader yerine kullanılabilir. İkincisi, tüm çağrıları BufferedReader nesnesinin yapıcısına iletilmesi gereken orijinal Reader nesnesine yönlendirir. . Örneğin:"

Reader readerOriginal = new UserCustomReader();
Reader reader = new BufferedReader(readerOriginal);

"Üçüncü yöntem, dinamik bir proxy (Proxy) oluşturmaktır."

"Java'da (java.lang.reflect.Proxy) program yürütme sırasında (dinamik olarak) ayrı bir sınıf oluşturmadan bir nesne oluşturmanıza gerçekten izin veren özel bir sınıf vardır."

"Bunu yapmak çok kolay:"

Reader reader = (Reader)Proxy.newProxyInstance();

"Bu benim için zaten yeni bir şey!"

"Ama elbette, yöntemi olmayan bir nesneye ihtiyacımız yok. Nesnenin yöntemleri olması ve istediğimizi yapmaları için onlara ihtiyacımız var. Java, bunun için InvocationHandler adlı özel bir arabirim kullanır ve bu arabirim, tüm yöntem çağrılarını kesebilir . proxy nesnesi ile ilişkili . Bir proxy nesnesi yalnızca arabirimler kullanılarak oluşturulabilir."

" Çağırma - birincil görevi basitçe bir yöntemi çağırmak olan bir yöntem veya sınıfın standart adıdır."

" İşleyici – bazı olayları işleyen bir sınıfın standart adıdır. Örneğin, fare tıklamalarını işleyen bir sınıfa MouseClickHandler, vb. adı verilir."

"InvocationHandler arabiriminin , proxy nesnesine yapılan tüm çağrıların yönlendirildiği tek bir çağırma yöntemi vardır . Örneğin:"

kod
Reader reader = (Reader)Proxy.newProxyInstance(new CustomInvocationHandler());
reader.close();
class CustomInvocationHandler implements InvocationHandler
{
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 {
  System.out.println("yes!");
  return null;
 }
}

" okuyucu . close () yöntemi çağrılırken , invoke yöntemi çağrılacak ve ekranda 'evet!' mesajı görüntülenecek."

"Böylece, bir CustomInvocationHandler sınıfı bildirdik ve InvocationHandler arabirimini ve onun invoke yöntemini uyguladık. invoke yöntemi çağrıldığında 'yes!' gösteriyor. Sonra bir CustomInvocationHandler nesnesi oluşturduk ve onu oluştururken newProxyInstance yöntemine geçirdik. bir proxy nesnesi."

"Evet, hepsi doğru."

"Bu çok güçlü bir araçtır. Genellikle bu proxy'ler, fiziksel olarak başka bir bilgisayarda çalışan programlardaki nesneleri simüle etmek veya erişimi kontrol etmek için oluşturulur  ."

"Bu yöntemde mevcut kullanıcının izinlerini kontrol edebilir, hataları işleyebilir, hataları günlüğe kaydedebilir ve çok daha fazlasını yapabilirsiniz."

"İşte invoke yönteminin orijinal nesnenin yöntemlerini de çağırdığı bir örnek:"

kod
Reader original = new UserCustomReader();

Reader reader = (Reader)Proxy.newProxyInstance(new CustomInvocationHandler(original));
reader.close();
class CustomInvocationHandler implements InvocationHandler
{
 private Reader readerOriginal;

 CustomInvocationHandler(Reader readerOriginal)
 {
  this.readerOriginal = readerOriginal;
 }

 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 {
  if (method.getName().equals("close"))
  {
   System.out.println("Reader closed!");
  }

  // This calls the readerOriginal object's close method.
  // The method's name and a description of its parameters are stored in the method variable.
  return method.invoke(readerOriginal, args);
 }
}

"Bu örneğin iki özelliği var."

"İlk olarak, «orijinal» Reader nesnesi yapıcıya iletilir ve CustomInvocationHandler içine bir referans kaydedilir .

"İkincisi, aynı yöntemi invoke yönteminde tekrar çağırıyoruz, ancak bu sefer «orijinal» nesnede."

"Ah. Başka bir deyişle, bu son satır aynı yöntemi çağırıyor ama orijinal nesnede:"

return method.invoke(readerOriginal, args);

"Evet."

"Çok bariz olduğunu söyleyemem ama yine de anlaşılabilir. Ya da öyle görünüyor."

"Harika. Sonra bir şey daha. newProxyInstance yönteminde, bir proxy nesnesi oluşturmak için biraz daha temizlik bilgisi iletmeniz gerekiyor. Ancak canavarca proxy nesneleri yaratmadığımız için, bu bilgi orijinal sınıfın kendisinden kolaylıkla elde edilebilir. "

"İşte başka bir örnek:"

kod
Reader original = new UserCustomReader();

ClassLoader classLoader = original.getClass().getClassLoader();
Class<?>[] interfaces = original.getClass().getInterfaces();
CustomInvocationHandler invocationHandler = new CustomInvocationHandler(original);

Reader reader = (Reader)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
class CustomInvocationHandler implements InvocationHandler
{
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 {
  return null;
 }
}

"Ah. ClassLoader ve arabirim listesi. Bu Reflection'dan bir şey, değil mi?"

"Evet."

"Anlıyorum. Sanırım ihtiyacım olursa ilkel, süper basit bir proxy nesnesi yaratabilirim."

"O zaman git Diego'yu kontrol et."