الأساسيات: يتطلب أفكار التصميم الموجهة نحو الكائن ، والأفكار المتعددة الأشكال ، وأفكار الانعكاس ؛
يسمح ظهور آلية الوكيل الديناميكي Java Dynamic لمطوري Java بالحصول على فصول وكيل ديناميكي دون الحاجة إلى كتابة فصول وكيل يدويًا. فئة الوكيل مسؤولة عن إرسال جميع مكالمات الطريقة إلى كائن المندوب لتعكس التنفيذ. أثناء عملية تنفيذ الإرسال ، يمكن للمطورين أيضًا ضبط كائن المفوض ووظائفه حسب الحاجة. هذا إطار عمل مرن ومرن للغاية. من خلال قراءة هذا المقال ، سيكون لدى القراء فهم أعمق لآلية الوكيل الديناميكي Java. تقوم هذه المقالة أولاً بتحليل الكود بناءً على آلية التشغيل وخصائص الوكيل الديناميكي Java وتجني التنفيذ الداخلي لفئات التوليد الديناميكي.
المفاهيم الأساسية وتصنيف نموذج الوكيل
وضع الوكيل: يوفر وكيلًا للكائنات الأخرى للتحكم في الوصول إلى هذا الكائن. يعمل كائن الوكيل كوسيط ، ويمكنه إزالة الخدمات أو إضافة خدمات إضافية ، أو اقتباس الآخرين: "إن فئة الوكيل مسؤولة عن الرسائل المسبقة للمعالجة لفئة المندوبين ، وتصفية الرسائل وإعادة توجيه الرسائل ، وإجراء المعالجة اللاحقة بعد تنفيذ الرسالة من قبل فئة المندوب."
سيناريوهات وضع الوكيل في التطوير
الوكيل البعيد: يوفر كائنات تمثيلية LAN للكائنات من المناطق الجغرافية المختلفة.
الوكيل الظاهري: تأخير الكائنات التي تستهلك الكثير من الموارد حسب الحاجة وإنشاءها عندما تكون هناك حاجة إليها بالفعل. على سبيل المثال ، يتم عرض النص أولاً ثم يتم عرض الصورة على صفحة الويب.
وكيل الحماية: يتحكم في حقوق الوصول لمستخدمي مختلفين. على سبيل المثال: فقط بعد نجاح تسجيل العميل ، يمكن إجراء عمليات الإضافة وحذف وتعديل والتحقق.
الوكيل المرجعي الذكي: يوفر خدمات إضافية للوكيل المستهدف.
كيفية تنفيذ وضع الوكيل
أيهما أفضل لتنفيذ الوكيل الديناميكي باستخدام الميراث والتجميع!
الواجهة العامة متحركة {public void move () ؛} تنفذ سيارة الفئة العامة {Override public void move () {try {thread.sleep (new random (). nextint (1000)) ؛ system.out.println ("... driving ...") ؛ Car2 يمتد Car {Override public void move () {// افصل الكود ، وزيادة منطق العمل الطويل = system.currentTimeMillis () ؛ system.out.println ("السيارة تبدأ في القيادة ...") ؛ super.move () "+(Endtime-StartTime)+" MS ") ؛}}طريقة الميراث لتنفيذ الوكيل
Moveablecar2=newCar2();
car2.move();
طريقة التجميع تنفذ الوكيل
Carcar=newCar();
Moveablem=newCar3(car);
m.move();
لخص
طريقة الميراث ليست مرنة بما فيه الكفاية. عندما يتم تثبيت الوظائف ، يمكنك فقط توسيع فئة الوكيل.
باستخدام التجميع ، يمكن نقل الوكلاء إلى بعضهم البعض ، ويمكن دمج الوكيل بمرونة ؛
الطبقة العامة Carlogproxy يمتد Car {Override public void move () {// افصل الكود وزيادة منطق العمل الطويل = System.CurrentTimeMillis () ؛ system.out.println ("login start ...") ؛ super.move () Cartimeproxy ينفذ {cartimeproxy (Car Car) {car) {super () ؛ this.car = car ؛} private carcar ؛ Override public void move () {// افصل الكود وأضف منطق العمل الطويل = system.currenttimeMillis () ؛ system.out.println ( Endtime = system.currentTimeMillis () ؛ system.out.println ("تنتهي السيارة إلى القيادة ... الوقت:"+(Endtime-StartTime)+"MS") ؛ Carlogproxy (CTP) ؛ clp.move () ؛ // يمكنك أيضًا تمرير مثيلات الوكيل إلى بعضها البعض من خلال واجهات Carlogproxy clp1 = new carlogproxy (car) ؛ cartimeproxy ctp1 = cartimeproxy الجديد (ctp1) ؛ ctp1.move () ؛JDK Dynamic Proxy و CGLIB الوكيل الديناميكي
الوكيل الديناميكي JDK
تنفيذ الوكيل
ما الذي يجب القيام به إذا أرادت كائنات مختلفة تنفيذ فئة الوكيل بنفس الوظيفة؟
في هذا الوقت ، يمكنك محاولة دمجه في نفس فئة الوكيل ------- الوكيل الديناميكي: تنفيذ الوكيل لفئات مختلفة/طرق مختلفة ؛
العملية العامة كما يلي:
تقع فئة الوكيل الديناميكي Java تحت حزمة java.lang.reflect ، والتي تنطوي بشكل عام على الفئتين التاليتين:
(1) interfaceInvocationHandler: يتم تعريف طريقة واحدة فقط في هذه الواجهة publicoBjectInvoke (ObjectObj ، MotherMethod ، Object [] args)
OBJ: يشير بشكل عام إلى فئة الوكيل
الطريقة: هي طريقة الوكيل
ARGS هي مجموعة من المعلمات لهذه الطريقة.
يتم تنفيذ هذه الطريقة التجريدية ديناميكيًا في فئة الوكيل.
(2) الوكيل: هذه الفئة هي فئة وكيل ديناميكي
statixObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)
إرجاع مثيل فئة الجليكوسيد ، ويمكن استخدام فئة الوكيل التي تم إرجاعها كفئة الوكيل (يمكنك استخدام الطريقة المعلنة في الواجهة بواسطة فئة الوكيل) ؛
مثال التنفيذ:
@ TimeHandler Public Class Handler تنفذ InvocationHandler {public timehandler (هدف الكائن) {super () ؛ this.target = target ؛} private ObjectTarget ؛/*** المعلمات:* proxy prox abject* mething mething stows strows) startTime = system.currentTimeMillis () ؛ system.out.println ("تبدأ السيارة في القيادة ...") ؛ method.invoke (الهدف) ؛ endtime طويل = system.currentTimeMillis () @واجهة الواجهة العامة من فئة الوكيل {public void move () ؛}@فئة الوكيل تنفذ سيارة الفئة العامة التي تنفذ {Override public void move () {try {thread.sleep (new Random (). nextint (1000)) ؛ system.out.println ("... ryving ...") ؛@امتحان
اختبار الفئة العامة { / *** JDK Dynamic Proxy Test Class* / Public Static Void Main (String [] args) {car car = new Car () ؛ InvocationHandler H = New Time -Handler (Car) ؛ class <؟> cls = car.getClass () ؛ /** loader class loader* واجهات تنفيذ الواجهة* h invocationHandler*/ movable m = (متحرك) proxy.newproxyinstance (cls.getClassloader () ، cls.getInterfaces () ، h) ؛ M.Move () ؛ }}&& نتائج الاختبار
ملخص
DynamicProxy هو مثل هذا الفئة:
إنه فئة تم إنشاؤها في وقت التشغيل. يحتاج هذا الفصل إلى تنفيذ مجموعة من الواجهات. عند استخدام فئات الوكيل الديناميكي ، يجب تنفيذ واجهة InvocationHandler.
الخطوات العامة للوكيل الديناميكي JDK
1. قم بإنشاء فئة تنفذ واجهة invocationHandler ، والتي يجب تنفيذها invoke ()
2. إنشاء فئة الوكيل والواجهة
3. استدعاء الطريقة الثابتة لبروكسي لإنشاء فئة وكيل
NewProxyInstance (ClassLoaderLoader ، فئة [] واجهات ، InvocationHandlerH)
4. طرق الاتصال من خلال الوكيل
تنفيذ الوكيل الديناميكي CGLIB
تنفيذ الوكيل
introducing cglib-node-2.2.jar package
cglibpproxy intercept فئة تنفذ طريقة الواجهة: إعادة كتابة طريقة اعتراض
الفئة العامة cglibproxy تنفذ methodInterceptor {private ensancerenhancer = new ensancer () ؛ كائن عام getProxy (class cl) {// قم بتعيين الفئة التي تنشئ فئة فرعية محسّنة. طريقة ARGS* مثيل وكيل من فئة الوكيل**/@@@interride اعتراض الكائن العام (الكائن OBJ ، الطريقة M ، Object [] args ، methodproxy proxy) يلقي رمي {system.out.println ("login start ...") باطل؛}}proxy فئة القطار
قطار الفئة العامة {public void move () {system.out.println ("القطار يقود ...") ؛ }}Test Class
اختبار الفئة العامة { / *** cglibproxy فئة اختبار الوكيل الديناميكي* / public static void main (string [] args) {cglibproxy proxy = new cglibproxy () ؛ Train t = (Train) proxy.getProxy (Train.class) ؛ T.Move () ؛ }}## نتائج الاختبار:
ملخص
الخطوات العامة لتنفيذ الوكيل الديناميكي باستخدام cglibproxy
1. إنشاء فئة لتنفيذ مفهوم الواجهة وتجاوز طريقة التقاطع
2. إنشاء فئة وكيل
3. اتصل بالطريقة المخصصة لفئة الوكيل للحصول على مثيل وكيل
4. اتصل بالطريقة التي يجب تنفيذها بواسطة مثيل الوكيل
ملخص مقارن
الوكيل الديناميكي JDK
1. فئات الوكيل فقط التي تنفذ واجهات
2. لا يمكن للفئات بدون واجهة تنفيذ وكيل ديناميكي لـ JDK
CGLIB الوكيل الديناميكي
1. تنفيذ الوكيل للدروس
2. قم بإنشاء فئة فرعية إلى فئة هدف التنفيذ ، واستخدم طريقة اعتراض التكنولوجيا لاعتراض جميع مكالمات طرق الفئة الأصل.
محاكاة خطوات توليد الوكيل
الأفكار:
وظيفة التنفيذ: أعد كائن الوكيل من خلال NewProxyInstance من Proxy
1. إعلان قطعة من الكود المصدر (وكيل الجيل الديناميكي)
2. قم بتجميع الكود المصدري (JDKCompilerapi) لإنشاء فئات جديدة (فئات وكيل)
3. قم بتحميل هذه الفئة في الذاكرة وإنشاء كائن جديد (كائن وكيل)
4. إرجاع كائن الوكيل
تحسين تنفيذ الوكيل الديناميكي
أولاً ، نحصل على برنامج التحويل البرمجي للنظام ، ونحصل على مدير الملفات من خلال المترجم ، ثم الحصول على الملف. ثم يقوم المترجم بمهمة التجميع. بعد الانتهاء من التجميع ، نقوم بتحميل ملف الفئة في محمل الفئة ، ونحصل على المثيل من خلال طريقة المنشئ ، ثم الاتصال NewInstance () لتلقي مثيل لكائن.
(1) احصل على برنامج التحويل البرمجي JavacompilerCompiler = ToolProvider.getSystemJavAcompiler () ؛
(2) مدير الملف standardjavafileManagerFileMgr = compiler.getStandardFileManager (null ، null ، null) ؛
(3) احصل على ملف iterableUnits = filemgr.getjavafileObjects (اسم الملف) ؛
(4) Compilation Task CompilationTaskt = compiler.getTask (null ، filemgr ، null ، null ، null ، null ، units) ؛
(5) تحميل على الذاكرة
classloadercl = classLoader.getSystemClassLoader () ؛
classc = cl.loadClass ("com.imooc.proxy. $ proxy0") ؛
(6) بناء مثيل من خلال مُنشئ كائن الوكيل
ConstructorCtr = C.GetConstructor (InFCE) ؛
ctr.newinstance (newcar ()) ؛
--------
كما ذكر أعلاه ، فإن منطق العمل الداخلي مرمز. كيفية تنفيذ الوكيل الديناميكي الحقيقي ومنطق الأعمال المعين ديناميكيا؟
1. تحتاج إلى إنشاء معالج معاملات. أولاً ، تقوم بإنشاء واجهة ، أي InvocationHandler. من أجل محاكاة JDK ، فإن اسم الواجهة هو نفس اسم معالج معاملة JDK. يمكنك أيضًا كتابة طريقة تسمى Invoke () ، والتي يتم استخدامها لتمثيل طريقة معينة لكائن لمعالجة الأعمال. لذلك ، تحتاج إلى تمرير كائن معين وطريقة الكائن كمعلمات لطريقة Invoke (). استدعاء (ObjectObj ، MotherMethod) ، الطريقة المستخدمة كمعلمة لانعكاس Java ، ويجب تقديم هذه الحزمة. وبهذه الطريقة ، تم الانتهاء من واجهة InvocationHandler.
2. قم بإنشاء فئات تنفيذ معالجة المعاملات ، مثل TimerProxy ، لتنفيذ واجهة InvocationHandler ، بحيث يصبح الهيكل
― ― - timerProxyImplementInvocationHandler { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――�تحتاج إلى تمرير الكائن الهدف فيه. إذا لم يكن لديك معلمات ، فلا يمكنك كتابة معلمات. قم بإنشاء طريقة إنشاء كائن الوكيل وتهيئة الكائن الهدف.
3. في طريقة NewProxyInstance () لفئة الوكيل ، بالإضافة إلى استخدام واجهة الفئة الهدف كمعلمة ، تحتاج أيضًا إلى تمرير معالج المعاملات المحدودة ، ثم تغيير الجزء المتصل من كائن المثيل الذي تم إنشاؤه واستخدام طريقة معالج المعاملة لاستبداله. تكمن الصعوبة في الربط بين الأوتار.
لخص
في مشروعنا ، يكون لنمط الوكيل أهميته العملية. على سبيل المثال ، إذا كنا نريد الاتصال بفصل دراسي تحت حزمة جرة معينة ، فيمكننا إضافة بعض منطق الأعمال الخاص قبل استدعاء هذا الفصل. وتسمى هذه الطريقة أيضا البرمجة الموجهة نحو AOP. (أضف وظائف إضافية دون تغيير الوظائف الأصلية.)
ما ورد أعلاه هو كل التفسير التفصيلي لرمز الوكيل الديناميكي Java (نمط التصميم) في هذه المقالة ، وآمل أن يكون مفيدًا للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!