تنقسم إشعارات AOP الربيع إلى خمس فئات:
قبل النصيحة: تنفيذ أمام نقطة الاتصال. لن تؤثر المعاينة على تنفيذ نقطة الاتصال ما لم يتم طرح استثناء هنا.
إشعار الإرجاع العادي [بعد إرجاع المشورة]: تنفيذ بعد التنفيذ العادي لنقطة الاتصال. إذا تم إلقاء استثناء من قبل نقطة الاتصال ، فلن يتم تنفيذه.
إشعار إرجاع الاستثناء [بعد رمي المشورة]: تنفيذ بعد إلقاء استثناء من قبل نقطة الاتصال.
إشعار الإرجاع [بعد نصيحة (أخيرًا): بعد الانتهاء من التنفيذ ، سيتم تنفيذ محتويات إشعار الإرجاع سواء أكملت بشكل طبيعي أو يتم طرح استثناء.
حول النصيحة: حول النصيحة تحيط بنقطة الاتصال ، مثل ما قبل وبعد استدعاء الطريقة. هذا هو أقوى نوع الإخطار ، والذي يمكنه تخصيص بعض العمليات قبل وبعد مكالمات الطريقة.
يحتاج الإخطار المحيط أيضًا إلى تحديد ما إذا كان سيتم متابعة معالجة نقطة الانضمام (استدعاء طريقة العملية لـ ProteingJoinPoint) أو تنفيذ المقاطعة.
بعد ذلك ، سنقوم باختبار خمسة أنواع إشعار من خلال كتابة برنامج عينة:
تحديد الواجهة
package com.chenqa.springaop.example.service ؛ الواجهة العامة bankservice { / *** التحويل المصرفي المحاكاة* param من الحساب* param إلى حساب* param مبلغ نقل الحساب* regurn* / نقل منطقي العام (نموذج السلسلة ، سلسلة إلى ، حساب مزدوج) ؛}}اكتب فصول التنفيذ
package com.chenqa.springaop.example.service.impl ؛ استيراد com.chenqa.springaop.example.service.bankservice ؛ الطبقة العامة bcmbankserviceimpl تنفذ bankservice يوان ") ؛ } system.out.println (نموذج+"نقل إلى"+إلى+"الحساب المصرفي"+حساب+"يوان") ؛ العودة كاذبة }}
تعديل ملف تكوين الربيع وأضف ما يلي:
<!-Bankservice Bean-> <bean id = "bankservice"/> <!-Section-> <bean id = "myaspect"/> <!-تكوين AOP-> <aOP: config> <aop: side ref = "myAspect"> <aop: pointcut expression = "execution (*com.chenqa.springaop.example.service. id = "pointcut"/> <aop: قبل method = "قبل" pointcut-ref = "pointcut"/> <aop: بعد method = "بعد" pointcut-ref = "pointcut"/> <aop: method-therturning = "pointcut". <aop: حول method = "ound" pointcut-ref = "pointcut"/> </aop: side> </ aop: config>
كتابة برنامج اختبار
ApplicationContext Context = جديد classPathxMlapplicationContext ("spring-aop.xml") ؛ Bankservice Bankservice = context.getBean ("Bankservice" ، Bankservice.class) ؛ Bankservice.transfer ("Zhang San" ، "Li Si" ، 200) ؛ الإخراج بعد التنفيذ:
تغيير 200 في برنامج الاختبار إلى 50 ، ثم الإخراج بعد التنفيذ:
من نتائج الاختبار ، يمكن ملاحظة أن ترتيب تنفيذ الإخطارات الخمسة هو:
قبل الإلغاء ← الإخطار المحيط ← إشعار الإرجاع العادي/الإخطار بإرجاع الإرجاع → الإخطار ، يمكنك أداء عدة مرات لعرضه.
الحالة 1: يتم اعتراض طريقة فقط من قبل فئة جانب واحد
عندما يتم اعتراض طريقة واحدة فقط جانب واحد ، في أي ترتيب يتم تنفيذ النصائح المختلفة في هذا الجانب؟ من فضلك انظر:
إضافة فئة نقطة
يتم استخدام هذا النقاط لاعتراض جميع الطرق في جميع الفئات ضمن حزمة الاختبار.
اختبار الحزمة ؛ استيراد org.aspectj.lang.annotation.pointCut ؛ pinctcts pointcuts {pointcut (value = "in (test.*)") public void aopdemo () {}}أضف فئة الجانب
ستستخدم النصيحة في هذا الفصل نقطة نقطة أعلاه. يرجى الرجوع إلى سمة القيمة لكل نصيحة عند استخدامها.
اختبار الحزمة ؛ استيراد org.aspectj.lang.joinpoint ؛ import org.aspectj.lang.proceditingjoinpoint ؛ استيراد org.aspectj.lang.annotation. {system.out.println ("[Side1] قبل المشورة") ؛ } AROUND (value = "test.pointCuts.Aopdemo ()") void public on (proceedingJoinPoint PJP) يلقي رمي {system.out.println ("[Side1] حول النصيحة 1") ؛ pjp.proceed () ؛ System.out.println ("[Side1] حول المشورة 2") ؛ } AfterReturning (value = "test.pointcuts.aopdemo ()") public void effreturning (JoinPoint joinpoint) {system.out.println ("[[side1] lefreturning chide") ؛ } AfterThrowning (value = "test.pointCuts.Aopdemo ()") public void lefring (JoinPoint Joinpoint) {system.out.println ("[Side1] refrething eving") ؛ } After (value = "test.pointCuts.Aopdemo ()") void public بعد (JoinPoint JoinPoint) {system.out.println ("[Side1] نصيحة متأخرة") ؛ } apter (value = "test.pointCuts.Aopdemo ()") void public بعد (JoinPoint JoinPoint) {system.out.println ("[Side1] بعد المشورة") ؛ }}أضف وحدة تحكم اختبار
إضافة وحدة تحكم للاختبار. لا يوجد سوى طريقة واحدة في وحدة التحكم هذه ، لكنها ستتعامل بشكل مختلف وفقًا لقيم المعلمة: أحدهما هو إرجاع كائن بشكل طبيعي ، والآخر هو رمي استثناء (لأننا نريد اختبار نصيحة Afterthroing)
اختبار الحزمة ؛ استيراد test.exception.testException ؛ استيراد org.springframework.http.httpstatus ؛ استيراد org.springframework.web.bind.annotation. requestmapping (value = "/test" ، method = requestMethod.get) اختبار النتائج العامة (REQUESTPARAM BOOLEAN THERMEXCESTION) {// case 1 if (throwException) {system.out.println ("رمي استثناء") ؛ رمي TestException جديد ("Skic A Server Expression") ؛ } // case 2 system.out.println ("test ok") ؛ إرجاع نتيجة جديدة () {{this.setId (111) ؛ this.setName ("Mock A Offer") ؛ }} ؛ } نتيجة فئة ثابتة عامة {private int id ؛ اسم السلسلة الخاصة ؛ public int getId () {return id ؛ } public void setId (int id) {this.id = id ؛ } السلسلة العامة getName () {return name ؛ } public void setName (اسم السلسلة) {this.name = name ؛ }}}اختبار الوضع الطبيعي
أدخل عنوان URL التالي مباشرة في المتصفح وأدخل http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false
سنرى نتيجة الإخراج:
[الجانب 1] حول النصيحة 1 [الجانب 1] قبل المشورة موافق [الجانب 1] حول نصيحة 2 [الجانب 1] بعد المشورة [الجانب 1] بعد نصيحة
استثناءات اختبار
أدخل مباشرة عنوان URL التالي في المتصفح واضغط على http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true :
سنرى نتيجة الإخراج:
[الجانب 1] حول النصيحة 1 [الجانب 1] قبل AdviceThrow استثناء [الجانب 1] بعد النصيحة [الجانب 1] نصيحة متأخرة
ختاماً
عندما يتم اعتراض طريقة ما من قبل فئة جانب واحد فقط ، سيتم تنفيذ النصيحة داخل فئة الجانب بالترتيب التالي:
الوضع الطبيعي:
استثناء:
الحالة 2: يتم اعتراض نفس الطريقة بواسطة فئات جانب متعددة
فيما يلي مثال يتم اعتراضه بواسطة فئتين من الجانب.
في بعض الحالات ، بالنسبة لفئتين مختلفتين ، بغض النظر عما إذا كانت نصيحتهم تستخدم نفس النقاط أو النقاط المختلفة ، فقد يتسبب ذلك في اعتراضها بواسطة فئات جانب متعددة. لذلك ، في هذه الحالة ، في أي ترتيب تنفذ النصيحة في فئات الجوانب المتعددة هذه؟ من فضلك انظر:
لا يزال فئة Pointcut لم يتغير
أضف فئة جوانب جديدة
اختبار الحزمة ؛ import org.aspectj.lang.joinpoint ؛ import org.aspectj.lang.proceditingjoinpoint ؛ استيراد org.aspectj.lang.annotation. {system.out.println ("[Side2] قبل المشورة") ؛ } AROUND (value = "test.pointCuts.Aopdemo ()") void public on (proceedingJoinPoint PJP) رمي {system.out.println ("[Side2] حول نصيحة 1") ؛ pjp.proceed () ؛ System.out.println ("[Side2] حول excloy2") ؛ } AfterReturning (value = "test.pointCuts.Aopdemo ()") public void efferning (JoinPoint JoinPoint) {system.out.println ("[[SABNE2] lefreturning excloy") ؛ } AfterThrowing (value = "test.pointCuts.Aopdemo ()") public void lefring (JoinPoint joinpoint) {system.out.println ("[[side2] نصيحة متأخرة") ؛ } After (value = "test.pointCuts.Aopdemo ()") void public بعد (JoinPoint JoinPoint) {system.out.println ("[SOBNE2] نصيحة متأخرة") ؛ } After (value = "test.pointCuts.Aopdemo ()") void public بعد (JoinPoint JoinPoint) {system.out.println ("[Side2] بعد المشورة") ؛ }}وحدة تحكم الاختبار لم تتغير أيضًا
لا تزال تستخدم وحدة التحكم أعلاه. ولكن الآن يعترض كل من الجانب 1 و SINGLE2 الطرق في وحدة التحكم.
استمر في الاختبار أدناه!
اختبار الوضع الطبيعي
أدخل عنوان URL التالي مباشرة في المتصفح وأدخل http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false
سنرى نتيجة الإخراج:
[الجانب 2] حول النصيحة 1 [الجانب 2] قبل النصيحة [الجانب 1] حول النصيحة 1 [الجانب 1] قبل المشورة موافق [الجانب 1] حول نصيحة 2 [الجانب 1] بعد المشورة [الجانب 1] نصيحة [الجانب 2] حول نصيحة 2 [الجانب 2] بعد الحصول على نصيحة
لكن في هذا الوقت ، لا يمكنني استنتاج أن الجانب 2 يتم تنفيذه بالتأكيد قبل الجانب 1.
لا تصدق ذلك؟ يمكنك إعادة تشغيل الخادم وتحاول مرة أخرى ، ربما سترى نتائج التنفيذ التالية:
[الجانب 1] حول النصيحة 1 [الجانب 1] قبل النصيحة [الجانب 2] حول النصيحة 1 [الجانب 2] قبل المشورة موافق [الجانب 2] حول نصيحة 2 [الجانب 2] بعد المشورة [الجانب 2] نصيحة [الجانب 1] حول نصيحة 2 [الجانب 1] بعد الحصول على نصيحة
وهذا هو ، في هذه الحالة ، ترتيب تنفيذ الجانب 1 وجانب 2 غير معروف. فكيف تحلها؟ لا عجل ، سيتم إعطاء الحل أدناه.
استثناءات اختبار
أدخل مباشرة عنوان URL التالي في المتصفح واضغط على http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true :
سنرى نتيجة الإخراج:
[الجانب 2] حول النصيحة 1 [الجانب 2] قبل النصيحة [الجانب 1] حول النصيحة 1 [الجانب 1] قبل الدفاع عن استثناء [الجانب 1] بعد إلقاء المشورة [الجانب 2] بعد إلقاء المشورة
وبالمثل ، إذا قمت بإعادة تشغيل الخادم ثم اختباره مرة أخرى ، فقد ترى النتائج التالية:
[الجانب 1] حول النصيحة 1 [الجانب 1] قبل النصيحة [الجانب 2] حول النصيحة 1 [الجانب 2] قبل الدفاع عن استثناء [جانب 2] نصيحة متأخرة [الجانب 1] نصيحة متأخرة
وهذا يعني ، بنفس الطريقة ، لا يحدد ترتيب تنفيذ الجانب 1 و Side2 أيضًا في ظروف استثنائية.
لذلك في الحالة 2 ، كيف تحدد ترتيب تنفيذ كل جانب؟
هناك طريقتان:
بغض النظر عن الطريقة التي يتم استخدامها ، كلما كان الجانب الأصغر ، كلما تم تنفيذه أولاً.
على سبيل المثال ، نضيف التعليقات التوضيحية @order لـ APSect1 و Side2 على التوالي ، على النحو التالي:
order (5)@component@sidepublic class side1 {// ...}@order (6)@component@sidepublic class Side2 {// ...} بعد هذا التعديل ، يمكن التأكد من أنه في أي حال ، يتم تنفيذ النصيحة في الجانب 1 قبل النصيحة في الجانب 2. كما هو مبين في الشكل أدناه:
ملحوظة
إذا تم تعريف نصيحة متطابقة لنفس النقطة (على سبيل المثال ، تم تحديد اثنين قبل) ، فلا يمكن تحديد ترتيب تنفيذ هاتين النصيتين ، حتى إذا قمت بإضافة التعليق التوضيحي إلى هاتين النصيتين ، فلن ينجح ذلك. تذكر هذا.
للحصول على نصيحة @، بغض النظر عما إذا كانت لها قيمة إرجاع أم لا ، يجب أن تستدعي pjp.proceed () داخل الطريقة ؛ خلاف ذلك ، لن يتم تنفيذ الواجهة الموجودة في وحدة التحكم ، مما سيتسبب أيضًا في عدم تشغيل المشورة. على سبيل المثال ، نفترض أنه في ظل الظروف العادية ، يكون ترتيب التنفيذ هو "SOBNE2 -> APSECT1 -> وحدة التحكم". إذا حذفنا pjp.proceed () ؛ في AROUND في الجانب 1 ، سيكون الإخراج الذي نراه هو:
[الجانب 2] حول النصيحة 1 [الجانب 2] قبل النصيحة [الجانب 1] حول النصيحة 1 [الجانب 1] حول نصيحة 2 [الجانب 1] بعد المشورة [الجانب 1] تلبية النصيحة [الجانب 2] حول نصيحة 2 [الجانب 2]
من النتائج ، يمكننا أن نجد أن الواجهة الموجودة في وحدة التحكم لم يتم تنفيذها ، ولم يتم تنفيذ BeboEdVice في الجانب 1.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.