CodeGym /جاوا بلاگ /Random-SD /جاوا ۾ متحرڪ پراڪس
John Squirrels
سطح
San Francisco

جاوا ۾ متحرڪ پراڪس

گروپ ۾ شايع ٿيل
سلام اڄ اسان هڪ اهم ۽ دلچسپ موضوع تي غور ڪنداسين: جاوا ۾ متحرڪ پراکسي ڪلاس جي پيدائش. اهو بلڪل سادو ناهي، تنهنڪري اسان مثالن کي استعمال ڪندي ان کي سمجهڻ جي ڪوشش ڪنداسين :) تنهن ڪري، سڀ کان اهم سوال: متحرڪ پراکسي ڇا آهن ۽ اهي ڇا لاء آهن؟ هڪ پراڪسي ڪلاس اصل طبقي جي مٿان هڪ قسم جو ”اضافو“ آهي، جيڪو اسان کي اجازت ڏئي ٿو ته جيڪڏهن ضروري هجي ته اصل طبقي جي رويي کي تبديل ڪري سگهون. اهو ڇا مطلب آهي "رويي کي تبديل ڪرڻ" ۽ اهو ڪيئن ڪم ڪري ٿو؟ هڪ سادي مثال تي غور ڪريو. فرض ڪريو اسان وٽ هڪ پرسن انٽرفيس آهي ۽ هڪ سادو انسان ڪلاس آهي جيڪو هن انٽرفيس کي لاڳو ڪري ٿو
public interface Person {

   public void introduce(String name);

   public void sayAge(int age);

   public void sayWhereFrom(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("My name is " + this.name);
   }

   @Override
   public void sayAge(int age) {
       System.out.println("I am " + this.age + " years old");
   }

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

       System.out.println("I'm from " + this.city + ", " + this.country);
   }

   // ...getters, setters, etc.
}
اسان جي انسان طبقي جا 3 طريقا آهن: متعارف ڪرايا وڃن ٿا، عمر ۽ چوندا آهن ڪٿي. تصور ڪريو ته اسان هن ڪلاس کي آف دي شيلف JAR لائبريري جي حصي طور حاصل ڪيو ۽ اسان صرف ان جو ڪوڊ ٻيهر نه ٿا لکي سگهون. پر اسان کي پڻ ان جي رويي کي تبديل ڪرڻ جي ضرورت آهي. مثال طور، اسان کي خبر ناهي ته اسان جي اعتراض تي ڪهڙي طريقي سان سڏيو وڃي ٿو، پر اسان چاهيون ٿا ته اسان جو ماڻهو "هيلو!" (ڪو به ماڻهو پسند نٿو ڪري جيڪو بيوقوف آهي) جڏهن ڪنهن به طريقن کي سڏيو وڃي ٿو. متحرڪ پراکسيز - 2هن صورتحال ۾ اسان کي ڇا ڪرڻ گهرجي؟ اسان کي ڪجھ شين جي ضرورت پوندي:
  1. دعوت ڏيڻ وارو

هي ڇا آهي؟ InvocationHandler هڪ خاص انٽرفيس آهي جيڪو اسان کي اجازت ڏئي ٿو ته ڪنهن به طريقي واري ڪال کي اسان جي اعتراض ڏانهن روڪيو ۽ اضافي رويي کي شامل ڪريو جيڪو اسان کي گهربل آهي. اسان کي ضرورت آهي ته اسان جو پنهنجو انٽرسيپٽر ٺاهيو، يعني هڪ ڪلاس ٺاهيو جيڪو هن انٽرفيس کي لاڳو ڪري. اهو تمام سادو آهي:
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("Hi!");
       return null;
   }
}
اسان کي صرف هڪ انٽرفيس طريقو لاڳو ڪرڻ جي ضرورت آهي: invoke() . ۽، رستي ۾، اهو ڪري ٿو جيڪو اسان کي گهربل آهي: اهو اسان جي اعتراض کي سڀني طريقن جي ڪالز کي روڪي ٿو ۽ ضروري رويي کي شامل ڪري ٿو (اندر اندر invoke() طريقي سان، اسان "هاء!" ڪنسول ڏانهن ٻاھر ڪڍون ٿا).
  1. اصل اعتراض ۽ ان جا پراڪس.
اسان ان لاءِ پنهنجو اصل انسان اعتراض ۽ هڪ ”اضافو“ (پراکسي) ٺاهيندا آهيون:
import java.lang.reflect.Proxy;

public class Main {

   public static void main(String[] args) {

       // Create the original object
       Man arnold = new Man("Arnold", 30, "Thal", "Austria");

       // Get the class loader from the original object
       ClassLoader arnoldClassLoader = arnold.getClass().getClassLoader();

       // Get all the interfaces that the original object implements
       Class[] interfaces = arnold.getClass().getInterfaces();

       // Create a proxy for our arnold object
       Person proxyArnold = (Person) Proxy.newProxyInstance(arnoldClassLoader, interfaces, new PersonInvocationHandler(arnold));

       // Call one of our original object's methods on the proxy object
       proxyArnold.introduce(arnold.getName());

   }
}
اهو بلڪل سادو نه ٿو لڳي! مون خاص طور تي ڪوڊ جي هر لائن لاءِ تبصرو شامل ڪيو. اچو ته هڪ ويجهي نظر رکون ته ڇا ٿي رهيو آهي. پهرين لڪير ۾، اسان صرف اصل شئي ٺاهيندا آهيون جنهن لاءِ اسان پراڪس ٺاهينداسين. هيٺيون ٻه لائينون شايد توهان کي ڏکيائي ڏين ٿيون:
// Get the class loader from the original object
ClassLoader arnoldClassLoader = arnold.getClass().getClassLoader();

// Get all the interfaces that the original object implements
Class[] interfaces = arnold.getClass().getInterfaces();
دراصل، هتي ڪجھ به خاص ناهي ٿي رهيو آهي :) چوٿين لائن ۾، اسان استعمال ڪندا آهيون خاص پراڪس ڪلاس ۽ ان جو جامد نئون پروڪسي انسٽانس () طريقو:
// Create a proxy for our arnold object
Person proxyArnold = (Person) Proxy.newProxyInstance(arnoldClassLoader, interfaces, new PersonInvocationHandler(arnold));
اهو طريقو صرف اسان جي پراکسي اعتراض ٺاهي ٿو. اسان طريقي سان منتقل ڪريون ٿا اصل ڪلاس بابت معلومات، جيڪا اسان کي آخري مرحلي ۾ ملي هئي (ان جو ClassLoader ۽ ان جي انٽرفيس جي هڪ فهرست)، انهي سان گڏ اڳ ۾ ٺاهيل InvocationHandler اعتراض. اصلي شيء اها آهي ته اسان جي اصل آرنلڊ اعتراض کي انوائس هينڊلر ڏانهن منتقل ڪرڻ نه وساريو، ٻي صورت ۾ "هٿ ڪرڻ" لاء ڪجھ به نه هوندو :) اسان آخر ڇا ڪيو؟ اسان وٽ ھاڻي ھڪڙو پراکسي اعتراض آھي: proxyArnold . اهو شخص انٽرفيس جي ڪنهن به طريقن کي سڏي سگهي ٿو. ڇو؟ ڇو ته اسان ان کي ڏنل سڀني انٽرفيس جي هڪ فهرست هتي ڏني آهي:
// Get all the interfaces that the original object implements
Class[] interfaces = arnold.getClass().getInterfaces();

// Create a proxy for our arnold object
Person proxyArnold = (Person) Proxy.newProxyInstance(arnoldClassLoader, interfaces, new PersonInvocationHandler(arnold));
هاڻي اهو شخص انٽرفيس جي سڀني طريقن جي باري ۾ ڄاڻي ٿو . ان کان علاوه، اسان اسان جي پراڪس ڏانهن منتقل ڪيو هڪ PersonInvocationHandler اعتراض آرنلڊ اعتراض سان ڪم ڪرڻ لاء ترتيب ڏنل:
// Create a proxy for our arnold object
Person proxyArnold = (Person) Proxy.newProxyInstance(arnoldClassLoader, interfaces, new PersonInvocationHandler(arnold));
ھاڻي جيڪڏھن اسان پراڪسي اعتراض تي پرسن انٽرفيس جي ڪنھن به طريقي کي سڏيندا آھيون، اسان جو ھينڊلر ڪال کي روڪيندو آھي ۽ ان جي بدران ان جي پنھنجي invoke() طريقي تي عمل ڪندو آھي. اچو ته مکيه() طريقو هلائڻ جي ڪوشش ڪريون! ڪنسول آئوٽ:

Hi!
تمام سٺو! اسان ڏسون ٿا ته اصل Person.introduce() طريقي جي بدران، اسان جي PersonInvocationHandler() جي invoke() طريقي کي سڏيو ويندو آهي:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

   System.out.println("Hi!");
   return null;
}
"سلام!" ڪنسول تي ڏيکاريل آهي، پر اهو بلڪل اهو رويو ناهي جيڪو اسان چاهيون ٿا:/ جيڪو اسان حاصل ڪرڻ جي ڪوشش ڪري رهيا هئاسين اهو پهريون ڀيرو "هاءِ!" ۽ پوءِ اصل طريقو پاڻ کي سڏين ٿا، ٻين لفظن ۾، طريقو ڪال
proxyArnold.introduce(arnold.getName());
ظاهر ڪرڻ گهرجي "هاءِ! منهنجو نالو آرنلڊ آهي"، نه رڳو "هاءِ!" اسان اهو ڪيئن حاصل ڪري سگهون ٿا؟ اهو پيچيده ناهي: اسان کي صرف اسان جي هينڊلر ۽ invoke() طريقي سان ڪجهه آزادي وٺڻ جي ضرورت آهي :) ڌيان ڏيو ته هن طريقي سان ڪهڙا دليل منظور ڪيا ويا آهن:
public Object invoke(Object proxy, Method method, Object[] args)
invoke () ميٿڊ کي رسائي حاصل ڪئي آھي اصل ۾ سڏ ڪيل طريقي تائين، ۽ ان جي سڀني دليلن تائين (طريقي طريقو، Object[] args). ٻين لفظن ۾، جيڪڏهن اسان proxyArnold.introduce(arnold.getName()) طريقي کي سڏيندا آهيون ته جيئن invoke() طريقو سڏيو وڃي ان جي بدران introduce() ميٿڊ، ته پوءِ هن طريقي جي اندر اسان کي اصل تعارف () طريقي تائين رسائي آهي. ۽ ان جو دليل! نتيجي طور، اسين ڪري سگھون ٿا:
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("Hi!");
       return method.invoke(person, args);
   }
}
هاڻي invoke() ميٿڊ ۾ اسان اصل ميٿڊ ۾ ڪال شامل ڪئي آهي. جيڪڏهن اسان هاڻي اسان جي پوئين مثال مان ڪوڊ هلائڻ جي ڪوشش ڪريون ٿا:
import java.lang.reflect.Proxy;

public class Main {

   public static void main(String[] args) {

       // Create the original object
       Man arnold = new Man("Arnold", 30, "Thal", "Austria");

       // Get the class loader from the original object
       ClassLoader arnoldClassLoader = arnold.getClass().getClassLoader();

       // Get all the interfaces that the original object implements
       Class[] interfaces = arnold.getClass().getInterfaces();

       // Create a proxy for our arnold object
       Person proxyArnold = (Person) Proxy.newProxyInstance(arnoldClassLoader, interfaces, new PersonInvocationHandler(arnold));

       // Call one of our original object's methods on the proxy object
       proxyArnold.introduce(arnold.getName());
   }
}
پوء اسان ڏسنداسين ته هاڻي هر شي ڪم ڪري ٿي جيئن ان کي گهرجي :) ڪنسول آئوٽ:

Hi! My name is Arnold
جڏھن توھان کي ھن جي ضرورت پئجي سگھي ٿي؟ حقيقت ۾، اڪثر. ”متحرڪ پراڪسي“ ڊيزائن جو نمونو فعال طور تي مشهور ٽيڪنالاجيز ۾ استعمال ٿيندو آهي... اوه، رستي ۾، مان اهو ٻڌائڻ وساري ويس ته متحرڪ پراڪسي هڪ ڊزائن جو نمونو آهي! مبارڪون، توهان هڪ وڌيڪ سکيو! :) متحرڪ پراکسيز - 3مثال طور، اهو فعال طور تي مشهور ٽيڪنالاجيز ۽ سيڪيورٽي سان لاڳاپيل فريم ورڪ ۾ استعمال ٿيندو آهي. تصور ڪريو ته توهان وٽ 20 طريقا آهن جيڪي صرف انهن صارفن طرفان ڪيا وڃن جيڪي توهان جي پروگرام ۾ سائن ان ٿيل آهن. استعمال ڪندي جيڪي توهان سکيا آهن، توهان آساني سان انهن 20 طريقن ۾ شامل ڪري سگهو ٿا هڪ چيڪ اهو ڏسڻ لاءِ ته ڇا صارف هر طريقي ۾ تصديقي ڪوڊ کي نقل ڪرڻ کان سواءِ صحيح سندون داخل ڪيون آهن. يا فرض ڪريو ته توهان هڪ لاگ ٺاهڻ چاهيو ٿا جتي صارف جا سڀئي عمل رڪارڊ ڪيا ويندا. اهو پڻ آسان آهي پراکسي استعمال ڪندي. هينئر به، توهان صرف اسان جي مٿين مثال ۾ ڪوڊ شامل ڪري سگهو ٿا ته جيئن توهان invoke() کي ڪال ڪريو ته طريقي جو نالو ظاهر ٿئي ، ۽ اهو اسان جي پروگرام جو هڪ سپر سادو لاگ ٺاهيندو :) آخر ۾، هڪ اهم حد تي ڌيان ڏيو. هڪ پراکسي اعتراض انٽرفيس سان ڪم ڪري ٿو، نه ڪلاس. هڪ پراکسي هڪ انٽرفيس لاء ٺهيل آهي. هن ڪوڊ تي هڪ نظر وٺو:
// Create a proxy for our arnold object
Person proxyArnold = (Person) Proxy.newProxyInstance(arnoldClassLoader, interfaces, new PersonInvocationHandler(arnold));
هتي اسان ٺاهيندا آهيون هڪ پراڪسي خاص طور تي پرسن انٽرفيس لاءِ. جيڪڏهن اسان ڪلاس لاءِ پراڪس ٺاهڻ جي ڪوشش ڪريون، يعني ريفرنس جو قسم تبديل ڪري Man class ڏانهن ڪاسٽ ڪرڻ جي ڪوشش ڪريون، اهو ڪم نه ڪندو.
Person proxyArnold = (Person) Proxy.newProxyInstance(arnoldClassLoader, interfaces, new PersonInvocationHandler(arnold));

proxyArnold.introduce(arnold.getName());
ٿريڊ ۾ استثنا "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 انسان ڏانهن ڪاسٽ نٿو ڪري سگهجي، هڪ انٽرفيس هجڻ هڪ مڪمل گهرج آهي. پراڪسز انٽرفيس سان ڪم ڪن ٿا. اهو سڀ ڪجهه اڄ لاءِ آهي :) خير، هاڻي اهو سٺو ٿيندو ته چند ڪمن کي حل ڪيو وڃي! :) ٻئي دفعي تائين!
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION