JavaRush /Blog Jawa /Random-JV /Proxy Dinamis ing Jawa

Proxy Dinamis ing Jawa

Diterbitake ing grup
Hello! Dina iki kita bakal ndeleng topik sing rada penting lan menarik - nggawe kelas proxy dinamis ing Jawa. Ora gampang banget, mula ayo nyoba ngerteni kanthi conto :) Dadi, pitakonan sing paling penting: apa proxy dinamis lan kanggo apa? Kelas proxy minangka jinis "superstruktur" ing kelas asli, sing ngidini kita ngganti prilaku yen perlu. Apa tegese ngganti prilaku lan kepiye cara kerjane? Ayo padha ndeleng conto prasaja. Ayo dadi ngomong kita duwe antarmuka Personlan kelas prasaja Mansing ngleksanakake antarmuka iki
public interface Person {

   public void introduce(String name);

   public void sayAge(int age);

   public void sayFrom(String city, String country);
}

public class Man implements Person {

   private String name;
   private int age;
   private String city;
   private String country;

   public Man(String name, int age, String city, String country) {
       this.name = name;
       this.age = age;
       this.city = city;
       this.country = country;
   }

   @Override
   public void introduce(String name) {

       System.out.println("Меня зовут " + this.name);
   }

   @Override
   public void sayAge(int age) {
       System.out.println("Мне " + this.age + " years");
   }

   @Override
   public void sayFrom(String city, String country) {

       System.out.println("Я из города " + this.city + ", " + this.country);
   }

   //..геттеры, сеттеры, и т.д.
}
Kelas kita Manduwe 3 cara: ngenalke awakmu, sebutno umurmu, lan sebutno asalmu. Ayo bayangake yen kita nampa kelas iki minangka bagéan saka perpustakaan JAR sing wis siap lan ora bisa njupuk lan nulis ulang kode kasebut. Nanging, kita kudu ngowahi prilaku dheweke. Contone, kita ora ngerti cara apa sing bakal diarani obyek, mula kita pengin wong kasebut ngucapake "Halo!" nalika nelpon salah sawijining. (Ora ana sing seneng karo wong sing ora sopan). Proksi dinamis - 1Kepiye carane kudu tumindak ing kahanan kaya ngono? Kita bakal mbutuhake sawetara perkara:
  1. InvocationHandler

Opo iki? Bisa diterjemahake kanthi harfiah minangka "panggilan interceptor". Iki nggambarake tujuane kanthi akurat. InvocationHandleriku antarmuka khusus sing ngidini kita nyegat sembarang cara nelpon kanggo obyek lan nambah prilaku tambahan kita kudu. Kita kudu nggawe interceptor dhewe - yaiku, nggawe kelas lan ngleksanakake antarmuka iki. Iku cukup prasaja:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class PersonInvocationHandler implements InvocationHandler {

private Person person;

public PersonInvocationHandler(Person person) {
   this.person = person;
}

 @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

       System.out.println("Hello!");
       return null;
   }
}
Kita kudu ngleksanakake mung siji cara antarmuka - invoke(). Nyatane, nindakake apa sing kita butuhake - nyegat kabeh panggilan metode menyang obyek lan nambah prilaku sing dibutuhake (ing kene kita invoke()nyetak "Hello!" menyang konsol ing metode kasebut).
  1. Objek asli lan proxy.
Ayo nggawe obyek asli Manlan "superstructure" (proxy) kanggo:
import java.lang.reflect.Proxy;

public class Main {

   public static void main(String[] args) {

       //Создаем оригинальный an object
       Man vasia = new Man("Vasya", 30, "Санкт-Петербург", "Россия");

       //Получаем загрузчик класса у оригинального an object
       ClassLoader vasiaClassLoader = vasia.getClass().getClassLoader();

       //Получаем все интерфейсы, которые реализует оригинальный an object
       Class[] interfaces = vasia.getClass().getInterfaces();

       //Создаем прокси нашего an object vasia
       Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));

       //Вызываем у прокси an object один из методов нашего оригинального an object
       proxyVasia.introduce(vasia.getName());

   }
}
Ora katon prasaja banget! Aku khusus nulis komentar kanggo saben baris kode: ayo dideleng kanthi luwih rinci babagan apa sing kedadeyan ing kana.

Ing baris pisanan kita mung nggawe obyek asli sing bakal nggawe proxy. Rong baris ing ngisor iki bisa nyebabake sampeyan bingung:
//Получаем загрузчик класса у оригинального an object
ClassLoader vasiaClassLoader = vasia.getClass().getClassLoader();

//Получаем все интерфейсы, которые реализует оригинальный an object
Class[] interfaces = vasia.getClass().getInterfaces();
Nanging ana tenan apa-apa khusus arep ing kene :) Kanggo nggawe proxy, kita kudu ClassLoader(loader kelas) saka obyek asli lan dhaptar kabeh antarmuka sing kelas asli kita (i.e. Man). Yen sampeyan ora ngerti apa iku ClassLoader, sampeyan bisa maca artikel iki bab loading kelas menyang JVM utawa iki ing Habré , nanging ora keganggu banget karo durung. Cukup elinga yen kita entuk informasi tambahan sing bakal dibutuhake kanggo nggawe obyek proxy. Ing baris kaping papat kita nggunakake kelas khusus Proxylan cara statis newProxyInstance():
//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Cara iki mung nggawe obyek proxy kita. Kanggo cara kita ngirim informasi babagan kelas asli sing ditampa ing langkah sadurunge (lan ClassLoaderdhaptar antarmuka), uga obyek interceptor sing digawe sadurunge - InvocationHandler'a. Ingkang utama yaiku aja lali ngirim obyek asli kita menyang interceptor vasia, yen ora, ora bakal ana apa-apa kanggo "nyegat" :) Apa sing kita lakoni? Saiki kita duwe obyek proxy vasiaProxy. Bisa nelpon sembarang cara antarmukaPerson . Kenging punapa? Amarga kita menehi dhaptar kabeh antarmuka - ing kene:
//Получаем все интерфейсы, которые реализует оригинальный an object
Class[] interfaces = vasia.getClass().getInterfaces();

//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Saiki dheweke "ngerti" kabeh cara antarmuka Person. Kajaba iku, kita menehi proxy obyek PersonInvocationHandlersing dikonfigurasi kanggo nggarap obyek kasebut vasia:
//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Saiki, yen kita nelpon sembarang cara antarmuka ing obyek proxy Person, interceptor kita bakal "nyekel" telpon iki lan nglakokaké cara dhewe tinimbang invoke(). Ayo nyoba mbukak metode kasebut main()! Output konsol: Halo! apik tenan! Kita weruh yen tinimbang metode nyata, metode kita Person.introduce()diarani : invoke()PersonInvocationHandler()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

   System.out.println("Hello!");
   return null;
}
Lan konsol ditampilake "Halo!" Nanging iki dudu prilaku sing dikarepake: / Miturut ide kita, "Halo!" kudu ditampilake dhisik, banjur cara sing kita sebut kudu bisa digunakake. Ing tembung liyane, cara iki nelpon:
proxyVasia.introduce(vasia.getName());
ngirim output menyang console "Hello! Jenengku Vasya," lan ora mung "Halo!" Kepiye carane bisa nggayuh iki? Ora ana sing rumit: sampeyan mung kudu nggatekake interceptor lan metode kita invoke():) Pay manungsa waé kanggo argumen apa sing diterusake kanggo metode iki:
public Object invoke(Object proxy, Method method, Object[] args)
Sawijining metode invoke()nduweni akses menyang metode sing diarani tinimbang lan kabeh argumene (Metode metode, Obyek [] args). Ing tembung liyane, yen kita nelpon cara proxyVasia.introduce(vasia.getName()), lan tinimbang cara , introduce()cara diarani invoke(), ing cara kasebut kita duwe akses menyang metode asli introduce()lan argumen! Akibaté, kita bisa nindakake kaya iki:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class PersonInvocationHandler implements InvocationHandler {

   private Person person;

   public PersonInvocationHandler(Person person) {

       this.person = person;
   }

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       System.out.println("Hello!");
       return method.invoke(person, args);
   }
}
Saiki kita wis nambahake invoke()telpon menyang metode asli kanggo metode kasebut. Yen saiki kita nyoba mbukak kode saka conto sadurunge:
import java.lang.reflect.Proxy;

public class Main {

   public static void main(String[] args) {

       //Создаем оригинальный an object
       Man vasia = new Man("Vasya", 30, "Санкт-Петербург", "Россия");

       //Получаем загрузчик класса у оригинального an object
       ClassLoader vasiaClassLoader = vasia.getClass().getClassLoader();

       //Получаем все интерфейсы, которые реализует оригинальный an object
       Class[] interfaces = vasia.getClass().getInterfaces();

       //Создаем прокси нашего an object vasia
       Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));

       //Вызываем у прокси an object один из методов нашего оригинального an object
       proxyVasia.introduce(vasia.getName());
   }
}
banjur kita bakal weruh sing saiki kabeh dianggo minangka ngirim :) Console output: Hello! Jenengku Vasya, ngendi sampeyan butuh? Ing kasunyatan, akeh panggonan. Pola desain "proxy dinamis" aktif digunakake ing teknologi populer ... lan kanthi cara, aku kelalen ngandhani yen Dynamic Proxyiku pola ! Sugeng, sampeyan wis sinau liyane! :) Proksi dinamis - 2Dadi, aktif digunakake ing teknologi populer lan kerangka kerja sing ana gandhengane karo keamanan. Bayangake sampeyan duwe 20 cara sing mung bisa ditindakake dening pangguna sing mlebu ing program sampeyan. Nggunakake Techniques sing wis sinau, sampeyan bisa kanthi gampang nambah 20 cara iki mriksa kanggo ndeleng yen pangguna wis ngetik login lan sandhi, tanpa duplikat kode verifikasi dhewe ing saben cara. Utawa, contone, yen sampeyan pengin nggawe log ing ngendi kabeh tumindak pangguna bakal direkam, iki uga gampang ditindakake kanthi nggunakake proxy. Sampeyan bisa malah saiki: mung nambah kode kanggo conto supaya jeneng cara ditampilake ing console nalika disebut invoke(), lan sampeyan bakal entuk log prasaja saka program kita :) Ing mburi kuliah, mbayar manungsa waé kanggo siji penting watesan . Nggawe obyek proxy dumadi ing tingkat antarmuka, dudu tingkat kelas. Proxy digawe kanggo antarmuka. Deleng kode iki:
//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Ing kene kita nggawe proxy khusus kanggo antarmuka Person. Yen kita nyoba kanggo nggawe proxy kanggo kelas, sing, kita ngganti jinis link lan nyoba kanggo matak kanggo kelas Man, boten bakal bisa.
Man proxyVasia = (Man) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));

proxyVasia.introduce(vasia.getName());
Pangecualian ing thread "utama" java.lang.ClassCastException: com.sun.proxy.$Proxy0 ora bisa dikirim menyang Man Anane antarmuka minangka syarat wajib. Proxy dianggo ing tingkat antarmuka. Iku kabeh kanggo dina iki :) Minangka materi tambahan babagan topik proxy, aku bisa menehi rekomendasi video sing apik banget lan uga artikel sing apik . Saiki, luwih becik ngrampungake sawetara masalah! :) Sampai ketemu!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION