JavaRush /Java Blog /Random-TK /Java-da dinamiki proksi

Java-da dinamiki proksi

Toparda çap edildi
Salam! Bu gün has möhüm we gyzykly mowzuga serederis - Java-da dinamiki proksi sapaklaryny dörederis. Bu gaty ýönekeý däl, geliň muny mysallar bilen anyklamaga synanyşalyň :) Diýmek, iň möhüm sorag: dinamiki proksi näme we olar näme üçin? Proksi synpy, zerur bolsa özüni alyp barşyny üýtgetmäge mümkinçilik berýän asyl synpyň üstünden “ýokary gurluş” görnüşidir. Özüňi alyp barşyňy üýtgetmek nämäni aňladýar we nähili işleýär? Simpleönekeý bir meselä seredeliň. Bu interfeýsi amala aşyrýan interfeýsimiz Personwe ýönekeý synpymyz bar diýeliňMan
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);
   }

   //..геттеры, сеттеры, и т.д.
}
Biziň synpymyzda Man3 usul bar: özüňizi tanyşdyryň, ýaşyňyzy aýdyň we nirededigiňizi aýdyň. Geliň, bu synpy taýýar JAR kitaphanasynyň bir bölegi hökmünde alandygymyzy we koduny alyp we täzeden ýazyp bilmejekdigimizi göz öňüne getireliň. Şeýle-de bolsa, biz onuň özüni alyp barşyny üýtgetmeli. Mysal üçin, haýsy usulyň obýektimize çagyryljakdygyny bilemzok, şonuň üçinem haýsydyr birine jaň edeninde ilki bilen "Salam!" Diýmegini isleýäris. (edepsiz adamy hiç kim halamaýar). Dinamiki proksi - 1Şeýle ýagdaýda näme etmeli? Bize birnäçe zat gerek bolar:
  1. InvocationHandler

Bu näme? Göçme manyda “jaň saklaýjy” hökmünde terjime edilip bilner. Bu onuň maksadyny gaty takyk suratlandyrýar. InvocationHandlerobýektimize islendik usul jaňlaryny saklamaga we zerur goşmaça hereketleri goşmaga mümkinçilik berýän ýörite interfeýsdir. Öz interfeýsimizi ýasamaly, ýagny synp döretmeli we bu interfeýsi durmuşa geçirmeli. Bu gaty ýönekeý:
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;
   }
}
Diňe bir interfeýs usulyny durmuşa geçirmeli - invoke(). Aslynda, zerur zatlary edýär - obýektimize çagyryşlaryň hemmesini saklaýar we zerur häsiýeti goşýar (bu ýerde invoke()usulyň içindäki konsola “Salam!” Çap edýäris).
  1. Asyl obýekt we onuň wekili.
Geliň, özboluşly bir obýekt Manwe onuň üçin “ýokary gurluş” (proksi) döredeliň:
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());

   }
}
Gaty ýönekeý görünmeýär! Kodlaryň her setiri üçin ýörite teswir ýazdym: geliň, ol ýerde bolup geçýän zatlara has içgin seredeliň.

Birinji setirde diňe proksi döredjek asyl obýektimizi ýasaýarys. Aşakdaky iki setir bulaşyklyga sebäp bolup biler:
//Получаем загрузчик класса у оригинального an object
ClassLoader vasiaClassLoader = vasia.getClass().getClassLoader();

//Получаем все интерфейсы, которые реализует оригинальный an object
Class[] interfaces = vasia.getClass().getInterfaces();
Hereöne bu ýerde hakykatdanam üýtgeşik bir zat ýok :) Proksi döretmek üçin ClassLoaderasyl obýektiň (synp ýükleýjisi) we asyl synpymyzyň (ýagny Man) ýerine ýetirýän ähli interfeýsleriniň sanawy gerek. Munuň nämedigini bilmeseňiz , JVM-e sapaklary ýüklemek ýa- da Habrede şu makalanyClassLoader okap bilersiňiz , ýöne entek kän bir biynjalyk bolmaň. Proksi obýektini döretmeli boljak biraz goşmaça maglumat alýandygymyzy ýadyňyzdan çykarmaň. Dördünji setirde ýörite synp we onuň statiki usuly ulanýarys : ProxynewProxyInstance()
//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Bu usul diňe proksi obýektimizi döredýär. Usula, öňki ädimde alan asyl synpymyz baradaky maglumatlary ( ClassLoaderwe onuň interfeýsleriniň sanawy), şeýle hem ozal döreden interfeýsimiziň obýekti - InvocationHandler'a. Esasy zat, asyl obýektimizi saklaýjylara geçirmegi ýatdan çykarmaň vasia, ýogsam “saklamak” üçin hiç zat bolmaz :) Näme bilen gutardyk? Indi proksi obýektimiz bar vasiaProxy. Islendik interfeýs usullarynyPerson çagyryp biler . Näme üçin? Sebäbi biz ähli interfeýsleriň sanawyny geçdik - şu ýerde:
//Получаем все интерфейсы, которые реализует оригинальный an object
Class[] interfaces = vasia.getClass().getInterfaces();

//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Indi ähli interfeýs usullaryndan "habarly" Person. PersonInvocationHandlerMundan başga-da, proksi bilen obýekt bilen işlemek üçin düzülen obýekti geçirdik vasia:
//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Indi, proksi obýektinde haýsydyr bir interfeýs usulyna jaň etsek Person, saklaýjymyz bu jaňy “tutar” we ýerine öz usulyny ýerine ýetirer invoke(). Usuly işletmäge synanyşalyň main()! Konsol çykyşy: Salam! Gowy! Hakyky usulyň ýerine usulymyzyň Person.introduce()atlandyrylýandygyny görýäris : invoke()PersonInvocationHandler()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

   System.out.println("Hello!");
   return null;
}
Konsol bolsa “Salam!” Thisöne bu biziň almak isleýän häsiýetimiz däl: / Pikirimize görä, “Salam!” Ilki görkezilmeli, soň bolsa çagyrýan usulymyzyň özi işlemeli. Başgaça aýdylanda, bu usul jaň edýär:
proxyVasia.introduce(vasia.getName());
konsolyna çykmaly “Salam! Meniň adym Wasýa, diňe "Salam!" Muny nädip gazanyp bileris? Çylşyrymly zat ýok: diňe interfeýsimiz we usulymyz bilen azajyk pikirlenmeli bolarsyňyz invoke():) Bu usula haýsy argumentleriň berilýändigine üns beriň:
public Object invoke(Object proxy, Method method, Object[] args)
Usul invoke()ýerine atlandyrylýan usulyna we ähli argumentlerine (Usul usuly, Obýekt [] args) girip biler. Başga bir söz bilen aýdylanda, bir usul diýsek proxyVasia.introduce(vasia.getName())we usulyň ýerine introduce()bir usul diýilse , şol usulyň içinde asyl usula we argumente invoke()girip bileris ! introduce()Netijede, şuňa meňzeş bir zat edip bileris:
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);
   }
}
invoke()Indi usula asyl usula jaň goşduk . Indi öňki mysalymyzdan kody işletjek bolsak:
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());
   }
}
şonda indi hemme zadyň bolmalysy ýaly işleýändigini göreris :) Konsol çykyşy: Salam! Meniň adym Wasýa, nirä gerek bolup biler? Aslynda köp ýerler. “Dinamiki proksi” dizaýn nagşy meşhur tehnologiýalarda işjeň ulanylýar ... theogsa-da, Dynamic Proxybu nagyşdygyny aýtmagy ýatdan çykardym ! Gutlaýarys, başga birini öwrendiňiz! :) Dinamiki proksi - 2Şeýlelikde, howpsuzlyk bilen baglanyşykly meşhur tehnologiýalarda we çarçuwalarda işjeň ulanylýar. Programmaňyzyň diňe hasaba giren ulanyjylary tarapyndan ýerine ýetirilip bilinjek 20 usulyňyzyň bardygyny göz öňüne getiriň. Öwrenen usullaryňyzy ulanyp, ulanyjynyň giriş koduny we parolyny girizendigini ýa-da ýokdugyny barlamak üçin bu 20 usula aňsatlyk bilen goşup bilersiňiz, tassyklama koduny her usulda aýratyn gaýtalamazdan. Ora-da, meselem, ähli ulanyjy hereketleriniň ýazga alynjak gündeligini döretmek isleseňiz, proksi ulanmak hem aňsat. Häzirem mümkin: çagyrylanda usulyň ady konsolda görkezilmegi üçin diňe kod goşuň invoke()we programmamyzyň ýönekeý gündeligini alarsyňyz :) Leksiýanyň ahyrynda bir möhüm meselä üns beriň çäklendirme . Proksi obýekti döretmek synp derejesinde däl-de, interfeýs derejesinde ýüze çykýar. Interfeýs üçin proksi döredilýär. Bu koda göz aýlaň:
//Создаем прокси нашего an object vasia
Person proxyVasia = (Person) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));
Bu ýerde ýörite interfeýs üçin proksi döredýäris Person. Synp üçin proksi döretmäge synanyşsak, ýagny baglanyşygyň görnüşini üýtgedip, synpa oklamaga synanyşsak Man, hiç zat bolmaz.
Man proxyVasia = (Man) Proxy.newProxyInstance(vasiaClassLoader, interfaces, new PersonInvocationHandler(vasia));

proxyVasia.introduce(vasia.getName());
"Esasy" sapakda kadadan çykma java.lang.ClassCastException: com.sun.proxy. $ Proxy0 adama goýberilip bilinmez Interfeýsiň bolmagy hökmany talapdyr. Proksi interfeýs derejesinde işleýär. Bularyň hemmesi şu gün üçin :) Proksi mowzugyna goşmaça material hökmünde size ajaýyp wideo we gowy makala maslahat berip bilerin . Bolýar, indi birnäçe meseläni çözmek gowy bolardy! :) Görüşýänçäk!
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION