يقدم
كما نعلم جميعًا ، تعد AOP (البرمجة الموجهة نحو القسم) واحدة من ميزات أطر عمل الربيع. يوفر AOP قابلية التوسع عالية للغاية عن طريق تحديد مخاوف القطع المتقاطعة. فكيف يعمل AOP في الربيع؟ عندما لا يمكنك استخدام Core Java إلا ولكن تحتاج إلى تقنية AOP ، تصبح الإجابة على هذا السؤال أمرًا بالغ الأهمية. ليس ذلك فحسب ، في المقابلات المتعلقة بالوظائف التقنية المتقدمة ، غالبًا ما تظهر هذه الأسئلة كأسئلة اختبار. انظر ، حضر صديقي مؤخرًا مقابلة وطرح مثل هذا السؤال الصعب - كيفية تنفيذ AOP دون استخدام المكتبات الربيع والمكتبات ذات الصلة ، فقط Core Java. لذلك ، سأقدم مخططًا تفصيليًا في هذه المقالة لمساعدتك على فهم كيفية تنفيذ AOP باستخدام Core Java (بالطبع ، يتمتع هذا AOP ببعض القيود الوظيفية). لاحظ أن هذه المقالة ليست دراسة مقارنة لـ Spring AOP و Java AOP ، ولكنها برنامج تعليمي حول تنفيذ AOP بمساعدة أنماط التصميم المتأصلة في Java الأساسية.
أعتقد أن القراء يعرفون بالفعل ماهية AOP وكيفية استخدامه في إطار الربيع ، لذلك تركز هذه المقالة فقط على كيفية تنفيذ AOP دون استخدام الربيع. بادئ ذي بدء ، يجب أن نعرف أن Spring يستخدم تقنيتين: JDK Proxy و Cglib لتنفيذ AOP. يوفر JDK Dynamic Proxy طريقة مرنة لتوصيل طريقة وإجراء عمليات محددة ، ولكن يجب أن يكون هناك قيود عند إجراء العمليات: يجب توفير واجهة ذات صلة وفئة التنفيذ للواجهة أولاً. تدرب على خلق معرفة حقيقية ، دعونا نفهم هذه الجملة من خلال القضية! يوجد الآن برنامج حاسبة للقيام ببعض عمليات الرياضيات. لننظر في وظيفة التقسيم. السؤال في هذا الوقت هو: إذا كان الإطار الأساسي لديه بالفعل رمز لتنفيذ القسم ، فهل يمكننا اختطافه وإجراء التحقق الإضافي عند تنفيذ الرمز؟ الجواب نعم ، وسأثبت ذلك مع مقتطف الرمز الوارد أدناه. أولاً ، دعونا نلقي نظرة على رمز الواجهة الأساسية:
حاسبة الواجهة العامة {Public Int Calculate (int a ، int b) ؛}رمز فئة تنفيذ الواجهة هذه كما يلي:
فئة CANCLUTORIMPLES PROCALIMPLES CANCOLUTOR {Override Public Int Calculate (int a ، int b) {return a/b ؛ }}على افتراض أنه لا يمكننا إصلاح الكود أعلاه أو إجراء أي تغييرات على المكتبة الأساسية ، كيف يمكننا تنفيذ وظيفة التحقق بشكل مثالي؟ لماذا لا تجرب وظيفة الوكيل الديناميكي JDK.
الفئة العامة somethandler تنفذ invocationHandler {// الكود المحذوفة من أجل البساطة ... .. Override الكائن العام استدعاء (وكيل الكائن ، طريقة الطريقة ، الكائن [] params) رمي {// التحقق من صحة الأعمال المعقدة ونتيجة كائن المنطق = method.invoke (targetObject ، params) ؛ نتيجة العودة }}دعونا نرى كيف تعمل وظيفة التحقق التي يتم تنفيذها بواسطة JDK Dynamic Proxy من خلال فئة الاختبار.
الفراغ الثابت العام (سلسلة [] args) {calculatorimpl cultimpl = new calculatorimpl () ؛ calculator proxied = (calculator) proxyfactory.getProxy (calculator.class ، calcimpl ، someHandler new (culmpl)) ؛ int النتيجة = proxied.calculate (20 ، 10) ؛ System.out.println ("النتيجة النهائية :::" + نتيجة) ؛ }من النتائج ، يمكننا أن نرى أنه من خلال تطبيق واجهة InvocationHandler القوية ، يمكننا الحصول على تنفيذ التثبيت. وفقًا لوثائق JDK ، تستخدم واجهة InvocationHandler مثيل الوكيل للتعامل مع مكالمة الطريقة.
الآن نعلم أن طريقة Invoke () لـ InvocationHandler يمكن أن تساعدنا في حل المشكلة. لذلك دعونا نحل مشكلة جديدة - كيف يمكننا إجراء العمليات قبل وبعد تنفيذ الطريقة؟ لوضعها بشكل أكثر تحديداً ، هل يمكننا ربط طريقة بإضافة AOPs متعددة (قبل ، بعد ، حولها) (ملاحظة المترجم: النص الأصلي هو إضافة AOPs متعددة ، لكنني أعتقد أن المعالج يعمل كجوانب)؟ الجواب هو أيضا نعم. اتبع الخطوات أدناه لإنشاء قالب رمز مبسط لتلبية هذا المطلب:
طريقتان لتنفيذ AOP:
1. تنفيذ الوكيل الديناميكي المقدم من JDK
واجهة
واجهة عامة userbean {void getUser () ؛ adduser void () ؛ void updateUser () ؛ void deleteuser () ؛ } فئة التنفيذ الأصلية
الفئة العامة userbeanimpl تنفذ userbean {private string user = null ؛ userBeanImpl () {} userbeanimpl (string user) {this.user = user ؛ } السلسلة العامة getUserName () {return user ؛ } public void getUser () {system.out.println ("هذه طريقة getUser ()!") ؛ } public void setUser (string user) {this.user = user ؛ System.out.println ("هذا هو طريقة setuser ()!") ؛ } public void adduser () {system.out.println ("هذه طريقة adduser ()!") ؛ } public void updateUser () {system.out.println ("هذه طريقة updateUser ()!") ؛ } public void deleteuser () {system.out.println ("هذا هو طريقة deleteuser ()!") ؛ }} فئة الوكيل
استيراد java.lang.reflect.invocationHandler ؛ استيراد java.lang.reflect.method ؛ استيراد java.lang.reflect.proxy ؛ استيراد com.cignacmc.finance.bean.userbeanimpl ؛ الفئة العامة userbeanproxy تنفذ invocationHandler {private object targetObject ؛ userbeanproxy العامة (Object targetObject) {this.targetObject = targetObject ؛ } استدعاء الكائن العام (وكيل الكائن ، الطريقة ، الكائن [] args) يلقي رمي {userBeanimpl userbean = (userBeanimpl) targetObject ؛ username = userbean.getUserName () ؛ نتيجة الكائن = فارغة ؛ // الإذن حكم إذا (اسم المستخدم! = null &&! "". يساوي (اسم المستخدم)) {result = method.invoke (targetObject ، args) ؛ } نتيجة الإرجاع ؛ }}
فئة الاختبار
استيراد java.lang.reflect.proxy ؛ استيراد com.cignacmc.finance.bean.userbean ؛ استيراد com.cignacmc.finance.bean.userbeanimpl ؛ استيراد com.cignacmc.finance.proxy.userbeanproxy ؛ الطبقة العامة proxyexe {public static void main (string [] args) {system.out.println ("profired .........") ؛ userBeanImpl TargetObject = جديد userbeanimpl ("bob liang") ؛ userbeanproxy proxy = جديد userbeanproxy (TargetObject) ؛ // إنشاء كائن proxy userbean object = (userBean) proxy.newproxyinstance (targetObject.getClass (). getClassloader () ، targetObject.getClass (). object.adduser () ؛ System.out.println ("لا مثبت ............") ؛ TargetObject = جديد userBeanimpl () ؛ Proxy = جديد userbeanproxy (TargetObject) ؛ // إنشاء كائن proxy object = (userBean) proxy.newproxyinstance (targetObject.getClass (). getClassloader () ، targetObject.getClass (). object.adduser () ؛ }}
الإخراج:
ثبت ............ هذه طريقة adduser ()! لم يثبت ..........
من المثال أعلاه ، يمكن اعتراض Method Adduser () المسمى بنجاح ومعالجتها وفقًا لذلك.
2. إنشاء فئة بروكسي من خلال cglib
الميزة هي أن كائننا المستهدف لا يتطلب تنفيذ الفئة البدائية للواجهة.
الفئة العامة ClientBean {private string name = null ؛ العميل العام () {} العميل العام (اسم السلسلة) {this.name = name ؛ } public void addClient () {system.out.println ("هذا هو طريقة addClient ()!") ؛ } public void deleteclient () {system.out.println ("هذا هو طريقة deleteclient ()!") ؛ } public void getClient () {system.out.println ("هذه طريقة getClient ()!") ؛ } public void getClient () {system.out.println ("هذه طريقة getClient ())!") ؛ } public void updateClient () {system.out.println ("هذه طريقة updateClient ()!") ؛ } السلسلة العامة getClientName () {return name ؛ } public void setClientName (اسم السلسلة) {this.name = name ؛ }} فئة الوكيل
استيراد java.lang.reflect.method ؛ استيراد com.cignacmc.finance.bean.clientbean ؛ استيراد net.sf.cglib.proxy.enhancer ؛ استيراد net.sf.cglib.proxy.methodinterceptor ؛ استيراد net.sf.cglib.proxy.methodinterceptor ؛ استيراد net.sf.cglib.proxy.methodproxy ؛ الفئة العامة cglibproxy تنفذ methodInterceptor {private object targetObject ؛ الكائن العام CreateProxyObject (Object targetObject) {this.targetObject = targetObject ؛ Enhancer Enhancer = New Enhancer () ؛ ensancer.SetSuperClass (this.targetObject.getClass ()) ؛ ensancer.setCallback (هذا) ؛ إرجاع ensancer.create () ؛ } اعتراض الكائن العام (وكيل الكائن ، طريقة الطريقة ، الكائن [] args ، methodproxy methodproxy) يلقي رمي {clientbean clientbean = (clientbean) targetObject ؛ username string = clientBean.getClientName () ؛ نتيجة الكائن = فارغة ؛ if (username! = null &&! " } نتيجة الإرجاع ؛ }} فئة الاختبار
استيراد java.lang.reflect.proxy ؛ استيراد com.cignacmc.finance.bean.clientbean ؛ استيراد com.cignacmc.finance.bean.userbean ؛ استيراد com.cignacmc.finance.bean.userbeanimpl ؛ استيراد com.cignacmc.finance.proxy.cglibproxy ؛ استيراد com.cignacmc.finance.proxy.userbeanproxy ؛ Public Class Proxyexe {public static void main (string [] args) {system.out.println ("........ cglib proxy ............") ؛ System.out.println ("مثبت ...............") ؛ cglibproxy cproxy = cglibproxy () جديد ؛ ClientBean ClientBean = (ClientBean) cproxy.createproxyoBject (New ClientBean ("Bob Liang")) ؛ clientbean.addclient () ؛ System.out.println ("لا مثبت ...............") ؛ cproxy = جديد cglibproxy () ؛ ClientBean = (ClientBean) cproxy.createproxyobject (new ClientBean ()) ؛ clientbean.addclient () ؛ }}
الإخراج:
..... CGLIB Proxy .................. أثبتت ............ هذه طريقة addClient ()! لم يثبت ............