"Hai, Amigo."

"Hello, Rishi."

"Hari ini saya akan menerangkan topik baharu dan sangat menarik kepada anda: proksi dinamik" .

"Java mempunyai beberapa cara untuk menukar kefungsian kelas tertentu…"

"Kaedah pertama adalah warisan."

"Cara paling mudah untuk menukar gelagat kelas ialah mencipta kelas baharu yang mewarisi kelas asal (asas) dan mengatasi kaedahnya. Kemudian, daripada menggunakan kelas asal, anda menggunakan kelas terbitan. Contohnya:"

Reader reader = new UserCustomReader();

"Kaedah kedua ialah menggunakan kelas pembalut."

" BufferedReader ialah contoh kelas jenis ini. Pertama, ia mewarisi Reader . Dalam erti kata lain, ia boleh digunakan dan bukannya Reader. Kedua, ia mengubah hala semua panggilan ke objek Reader asal , yang mesti dihantar kepada pembina objek BufferedReader . Sebagai contoh:"

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

"Kaedah ketiga ialah mencipta proksi dinamik (Proksi)."

"Terdapat kelas khas dalam Java (java.lang.reflect.Proxy) yang sebenarnya membenarkan anda membina objek semasa pelaksanaan program (secara dinamik), tanpa mencipta kelas berasingan untuknya."

"Ini sangat mudah dilakukan:"

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

"Itu sudah menjadi sesuatu yang baru kepada saya!"

"Tetapi sudah tentu, kita tidak memerlukan objek tanpa kaedah. Kita memerlukan objek untuk mempunyai kaedah, dan kita memerlukannya untuk melakukan apa yang kita mahu. Java menggunakan antara muka khas untuk ini dipanggil InvocationHandler , yang boleh memintas semua panggilan kaedah dikaitkan dengan objek proksi. Objek proksi hanya boleh dibuat menggunakan antara muka."

" Invoke – ialah nama standard untuk kaedah atau kelas yang tugas utamanya ialah memanggil beberapa kaedah sahaja."

" Pengendali – ialah nama standard untuk kelas yang mengendalikan beberapa acara. Contohnya, kelas yang mengendalikan klik tetikus akan dipanggil MouseClickHandler, dsb."

"Antara muka InvocationHandler mempunyai kaedah invoke tunggal , yang mana semua panggilan ke objek proksi diarahkan . Contohnya:"

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

"Apabila memanggil kaedah . close () pembaca , kaedah invoke akan dipanggil dan skrin akan memaparkan 'ya!'"

"Jadi, kami mengisytiharkan CustomInvocationHandler, kelas dan melaksanakan antara muka InvocationHandler dan kaedah invokenya . Apabila kaedah invocation dipanggil, ia memaparkan 'ya!'. Kemudian kami mencipta objek CustomInvocationHandler dan menyerahkannya kepada kaedah ProxyInstance baru semasa mencipta objek proksi."

"Ya, itu semua betul."

"Ini adalah alat yang sangat berkuasa. Biasanya, proksi ini dicipta untuk mensimulasikan objek dalam program yang dijalankan secara fizikal pada komputer lain.  Atau untuk mengawal akses."

"Anda boleh menyemak kebenaran pengguna semasa, mengendalikan ralat, ralat log dan banyak lagi dalam kaedah ini."

"Berikut ialah contoh di mana kaedah invoke juga memanggil kaedah objek asal:"

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

"Contoh ini mempunyai dua ciri khas."

"Pertama, objek Pembaca «asal» diserahkan kepada pembina, dan rujukan kepadanya disimpan di dalam CustomInvocationHandler . "

"Kedua, kami memanggil kaedah yang sama sekali lagi dalam kaedah panggilan, tetapi pada objek «asal» kali ini."

"Ah. Dalam erti kata lain, baris terakhir ini memanggil kaedah yang sama, tetapi pada objek asal:"

return method.invoke(readerOriginal, args);

"Ya."

"Saya tidak akan mengatakan bahawa ia sangat jelas, tetapi ia masih boleh difahami. Atau nampaknya begitu."

"Hebat. Kemudian satu perkara lagi. Dalam kaedah ProxyInstance baharu, anda perlu menghantar lebih sedikit maklumat pengemasan untuk mencipta objek proksi. Tetapi kerana kami tidak mencipta objek proksi yang besar, maklumat ini mudah diperoleh daripada kelas asal itu sendiri. "

"Ini satu lagi contoh:"

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 dan senarai antara muka. Ini adalah sesuatu daripada Reflection, bukan?"

"Ya."

"Saya faham. Saya rasa saya boleh mencipta objek proksi yang primitif dan sangat mudah jika saya memerlukannya."

"Kalau begitu pergi daftar masuk dengan Diego."