"Hai, Amigo."

"Halo, Rishi."

"Hari ini saya akan menjelaskan topik baru dan sangat menarik untuk Anda: proxy dinamis" .

"Java memiliki beberapa cara untuk mengubah fungsionalitas kelas tertentu…"

"Metode pertama adalah warisan."

"Cara termudah untuk mengubah perilaku kelas adalah membuat kelas baru yang mewarisi kelas (basis) asli, dan mengganti metodenya. Kemudian, alih-alih menggunakan kelas asli, Anda menggunakan kelas turunan. Misalnya:"

Reader reader = new UserCustomReader();

"Metode kedua adalah menggunakan kelas pembungkus."

" BufferedReader adalah contoh dari jenis kelas ini. Pertama, ini mewarisi Reader . Dengan kata lain, ini dapat digunakan sebagai pengganti Reader. Kedua, ini mengalihkan semua panggilan ke objek Reader asli , yang harus diteruskan ke konstruktor objek BufferedReader . Misalnya:"

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

"Metode ketiga adalah membuat proxy dinamis (Proxy)."

"Ada kelas khusus di Java (java.lang.reflect.Proxy) yang benar-benar memungkinkan Anda membuat objek selama eksekusi program (secara dinamis), tanpa membuat kelas terpisah untuknya."

"Ini sangat mudah untuk dilakukan:"

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

"Itu sudah sesuatu yang baru bagiku!"

"Tapi tentu saja, kita tidak memerlukan objek tanpa metode. Kita memerlukan objek untuk memiliki metode, dan kita memerlukannya untuk melakukan apa yang kita inginkan. Java menggunakan antarmuka khusus untuk ini yang disebut InvocationHandler , yang dapat mencegat semua pemanggilan metode terkait dengan objek proxy. Objek proxy hanya dapat dibuat menggunakan antarmuka."

" Invoke – adalah nama standar untuk metode atau kelas yang tugas utamanya adalah memanggil beberapa metode."

" Handler – adalah nama standar untuk kelas yang menangani beberapa kejadian. Misalnya, kelas yang menangani klik mouse akan disebut MouseClickHandler, dll."

"Antarmuka InvocationHandler memiliki metode pemanggilan tunggal, di mana semua panggilan ke objek proxy diarahkan . Misalnya:"

Kode
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;
 }
}

"Saat memanggil metode reader .close (), metode invoke akan dipanggil, dan layar akan menampilkan 'yes!' "

"Jadi, kami mendeklarasikan CustomInvocationHandler, kelas, dan mengimplementasikan antarmuka InvocationHandler dan metode pemanggilannya . Saat metode pemanggilan dipanggil, ini menampilkan 'yes!'. Kemudian kami membuat objek CustomInvocationHandler , dan meneruskannya ke metode newProxyInstance saat membuat objek proxy."

"Ya, itu semua benar."

"Ini adalah alat yang sangat ampuh. Biasanya, proxy ini dibuat untuk mensimulasikan objek dalam program yang berjalan secara fisik di komputer lain.  Atau untuk mengontrol akses."

"Anda dapat memeriksa izin pengguna saat ini, menangani kesalahan, mencatat kesalahan, dan banyak lagi dalam metode ini."

"Ini adalah contoh di mana metode pemanggilan juga memanggil metode objek asli:"

Kode
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);
 }
}

"Contoh ini memiliki dua fitur khusus."

"Pertama, objek Pembaca «asli» diteruskan ke konstruktor, dan referensi ke sana disimpan di dalam CustomInvocationHandler . "

"Kedua, kita memanggil metode yang sama ini lagi dalam metode pemanggilan, tetapi kali ini pada objek «asli»."

"Ah. Dengan kata lain, baris terakhir ini memanggil metode yang sama, tetapi pada objek aslinya:"

return method.invoke(readerOriginal, args);

"Ya."

"Saya tidak akan mengatakan bahwa itu sangat jelas, tetapi masih bisa dimengerti. Atau begitulah tampaknya."

"Bagus. Lalu satu hal lagi. Dalam metode newProxyInstance, Anda perlu menyampaikan sedikit informasi tata graha untuk membuat objek proksi. Tetapi karena kami tidak membuat objek proksi yang mengerikan, informasi ini mudah diperoleh dari kelas asli itu sendiri. "

"Ini contoh lain:"

Kode
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 dan daftar antarmuka. Ini sesuatu dari Refleksi, bukan?"

"Ya."

"Begitu. Yah, kurasa aku bisa membuat objek proksi yang primitif dan super sederhana jika aku membutuhkannya."

"Kalau begitu, hubungi Diego."