الوكيل الديناميكي هو في الواقع فئة java.lang.reflect.Proxy التي تنشئ بايت فئة ديناميكيًا استنادًا إلى جميع الواجهات التي تحددها. سوف ترث هذه الفئة فئة الوكيل وتنفذ جميع الواجهات التي تحددها (صفيف الواجهة الذي تمرره في المعلمة ) ؛ ثم استخدم أداة تحميل الفئة التي حددتها لتحميل بايت الفئة في النظام، وأخيرًا قم بإنشاء كائن من هذه الفئة، وقم بتهيئة بعض قيم الكائن، مثل invocationHandler، وهي أعضاء الطريقة المتوافقة مع جميع الواجهات . بعد التهيئة، يتم إرجاع الكائن إلى العميل المتصل. بهذه الطريقة، ما يحصل عليه العميل هو كائن Proxy الذي ينفذ جميع واجهاتك. يرجى الاطلاع على تحليل المثال:
الواجهة العامة لمعالج الأعمال {
عملية الفراغ العامBusiness();
}
@تجاوز
عملية باطلة عامة () {
System.out.println("معالجة الأعمال...");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
*فئة وكالة الأعمال
* @author fanshadoop
*
*/
الطبقة العامة BusinessProcessorHandler تنفذ InvocationHandler {
هدف الكائن الخاص = فارغ؛
BusinessProcessorHandler(هدف الكائن) {
this.target = target;
}
استدعاء الكائن العام (وكيل الكائن، طريقة الطريقة، وسيطة الكائن [])
رميات قابلة للرمي {
System.out
.println("يمكنك القيام بشيء هنا قبل معالجة عملك");
نتيجة الكائن = الأسلوب.invoc(target, args);
System.out
.println("يمكنك القيام بشيء هنا بعد معالجة عملك");
نتيجة الإرجاع؛
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
اختبار الطبقة العامة {
/**
* @param args
*/
public static void main(String[] args) {
BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
BusinessProcessorHandler Handler = new BusinessProcessorHandler(bpimpl);
BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(
bpimpl.getClass().getClassLoader(), bpimpl.getClass()
.getInterfaces()، معالج)؛
bp.processBusiness();
System.out.println(bp.getClass().getName());
printClassDefinition(bp.getClass());
}
سلسلة ثابتة عامة getModifier(int modifier) {
نتيجة السلسلة = ""؛
التبديل (المعدل) {
معدل الحالة.خاص:
النتيجة = "خاص"؛
معدل الحالة.PUBLIC:
النتيجة = "عامة"؛
معدّل الحالة. محمي:
النتيجة = "محمية"؛
معدل الحالة. الملخص:
النتيجة = "مجردة"؛
معدل الحالة.النهائي:
النتيجة = "النهائي"؛
معدّل الحالة. أصلي:
النتيجة = "أصلية"؛
معدل الحالة. ثابت:
النتيجة = "ثابت"؛
معدّل الحالة. متزامن:
النتيجة = "متزامنة"؛
معدّل الحالة. صارم:
النتيجة = "صارمة"؛
معدل الحالة. عابر:
النتيجة = "عابرة"؛
معدل الحالة.VOLATILE:
النتيجة = "متقلبة"؛
معدل الحالة.الواجهة:
النتيجة = "الواجهة"؛
}
نتيجة الإرجاع؛
}
طباعة الفراغ الثابت العام (Class clz) {
String clzModifier = getModifier(clz.getModifiers());
إذا (clzModifier != null && !clzModifier.equals("")) {
clzModifier = clzModifier + " ";
}
String superClz = clz.getSuperclass().getName();
إذا (superClz != null && !superClz.equals("")) {
superClz = "يمتد" + superClz;
}
Class[] واجهات = clz.getInterfaces();
سلسلة inters = "";
لـ (int i = 0; i < واجهات. الطول; i++) {
إذا (ط == 0) {
inters += "التنفيذات";
}
inters += واجهات[i].getName();
}
System.out.println(clzModifier + clz.getName() + " " + superClz + " "
+ بين)؛
System.out.println("{");
Field[] الحقول = clz.getDeclaredFields();
لـ (int i = 0; i < field.length; i++) {
String modifier = getModifier(fields[i].getModifiers());
إذا (المعدل != null && !modifier.equals("")) {
المعدل = المعدل + " "؛
}
String fieldName = field[i].getName();
String fieldType = field[i].getType().getName();
System.out.println(" " + معدل + نوع الحقل + " " + اسم الحقل
+ "؛")؛
}
System.out.println();
الطريقة[] الطرق = clz.getDeclaredMethods();
لـ (int i = 0; i < الأساليب. الطول; i++) {
طريقة الطريقة = الأساليب[i];
معدل السلسلة = getModifier(method.getModifiers());
إذا (المعدل != null && !modifier.equals("")) {
المعدل = المعدل + " "؛
}
StringmethodName =method.getName();
Class returnClz =method.getReturnType();
String retrunType = returnClz.getName();
Class[] clzs =method.getParameterTypes();
سلسلة ParaList = "(";
لـ (int j = 0; j < clzs.length; j++) {
paraList += clzs[j].getName();
إذا (ي != clzs.length - 1) {
paraList += ", ";
}
}
paraList += ")";
clzs =method.getExceptionTypes();
استثناءات السلسلة = ""؛
لـ (int j = 0; j < clzs.length; j++) {
إذا (ي == 0) {
استثناءات += "رميات"؛
}
الاستثناءات += clzs[j].getName();
إذا (ي != clzs.length - 1) {
الاستثناءات += ", ";
}
}
الاستثناءات += ";";
String MethodPrototype = modifier + retrunType + " " + اسم الطريقة
+ ParaList + الاستثناءات؛
System.out.println(" "+methodPrototype);
}
System.out.println("}");
}
}
منطقية يساوي (java.lang.Object)؛
java.lang.String toString();
int hashCode();
عملية باطلة Business();
}
من الواضح أن طريقة Proxy.newProxyInstance ستقوم بالأمور التالية:
1. قم بإنشاء فئة ديناميكيًا بناءً على واجهات المعلمة الثانية التي تم تمريرها لتنفيذ الواجهة في الواجهات. في هذا المثال، هذه هي طريقةprocessBusiness لواجهة BusinessProcessor. ويرث فئة Proxy ويعيد كتابة ثلاث طرق مثل hashcode وtoString وequals. للحصول على تنفيذ محدد، يرجى الرجوع إلى ProxyGenerator.generateProxyClass(...); في هذا المثال، يتم إنشاء فئة $Proxy0
2. قم بتحميل الفئة التي تم إنشاؤها حديثًا في jvm من خلال المعلمة الأولى التي تم تمريرها، classloder. على وشك تحميل فئة $Proxy0
3. استخدم المعلمة الثالثة لاستدعاء مُنشئ $Proxy0 (InvocationHandler) لـ $Proxy0 لإنشاء كائن $Proxy0، واستخدم معلمة الواجهات لاجتياز جميع أساليب الواجهة الخاصة به وإنشاء كائن أسلوب لتهيئة العديد من متغيرات عضو الأسلوب في هدف.
4. أعد مثيل $Proxy0 إلى العميل.
انها بخير الآن. دعونا نرى كيف يقوم العميل بتعديله وسيصبح الأمر واضحًا.
1. يحصل العميل على كائن مثيل $Proxy0 نظرًا لأن $Proxy0 يرث BusinessProcessor، فلا توجد مشكلة في تحويله إلى BusinessProcessor.
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
2. bp.processBusiness();
ما يُسمى فعليًا هو $Proxy0.processBusiness(); ثم يتم تنفيذ $Proxy0.processBusiness() لاستدعاء طريقة الاستدعاء من خلال InvocationHandler!