การแจ้งเตือนฤดูใบไม้ผลิ AOP แบ่งออกเป็นห้าประเภท:
ก่อนคำแนะนำ: ดำเนินการต่อหน้าจุดเชื่อมต่อ ตัวอย่างจะไม่ส่งผลกระทบต่อการดำเนินการของจุดเชื่อมต่อเว้นแต่จะมีข้อยกเว้นถูกโยนลงที่นี่
การแจ้งเตือนการส่งคืนปกติ [หลังจากคำแนะนำส่งคืน]: ดำเนินการหลังจากการดำเนินการตามปกติของจุดเชื่อมต่อเสร็จสิ้น หากข้อยกเว้นถูกโยนลงโดยจุดเชื่อมต่อมันจะไม่ถูกดำเนินการ
การแจ้งเตือนการส่งคืนข้อยกเว้น [หลังจากคำแนะนำการขว้างปา]: ดำเนินการหลังจากข้อยกเว้นถูกโยนลงโดยจุดเชื่อมต่อ
การแจ้งเตือนแบบส่งคืน [หลังจากคำแนะนำ (สุดท้าย)]: หลังจากดำเนินการเสร็จสิ้นเนื้อหาของการแจ้งเตือนการส่งคืนจะถูกดำเนินการไม่ว่าจะเสร็จสมบูรณ์ตามปกติหรือมีข้อยกเว้นถูกโยนลงไป
คำแนะนำรอบ ๆ : คำแนะนำรอบ ๆ จุดเชื่อมต่อเช่นก่อนและหลังการโทรวิธี นี่เป็นประเภทการแจ้งเตือนที่ทรงพลังที่สุดซึ่งสามารถปรับแต่งการดำเนินการบางอย่างก่อนและหลังการโทร
การแจ้งเตือนโดยรอบยังจำเป็นต้องตัดสินใจว่าจะดำเนินการประมวลผลจุดเข้าร่วมต่อไป (เรียกวิธีกระบวนการของการดำเนินการ joinpoint) หรือการดำเนินการขัดจังหวะ
ต่อไปเราจะทดสอบการแจ้งเตือนห้าประเภทโดยการเขียนโปรแกรมตัวอย่าง:
กำหนดอินเทอร์เฟซ
แพ็คเกจ com.chenqa.springaop.example.service; อินเตอร์เฟสสาธารณะ Bankservice { / *** การโอนเงินธนาคารจำลอง* @param จากบัญชี* @param ไปยังบัญชี* @param บัญชีโอนจำนวนเงิน* @return* / การโอนบูลีนสาธารณะเขียนคลาสการใช้งาน
แพ็คเกจ com.chenqa.springaop.example.service.impl; นำเข้า com.chenqa.springaop.example.service.bankservice; ชั้นเรียนสาธารณะ bcmbankserviceimpl ใช้ Bankservice หยวน "); } system.out.println (แบบฟอร์ม+"โอนไปยัง"+ถึง+"บัญชีธนาคาร"+บัญชี+"หยวน"); กลับเท็จ; -
แก้ไขไฟล์การกำหนดค่าสปริงและเพิ่มสิ่งต่อไปนี้:
<!-bankservice bean-> <bean id = "bankservice"/> <!-ส่วน-> <bean id = "myaspect"/> <!-การกำหนดค่า AOP-> <aop: config> <aop: ref = "myaspect"> <aop: pointcut expression = id = "pointcut"/> <aop: ก่อนวิธีการ = "ก่อน" pointcut-ref = "pointcut"/> <aop: หลังจากวิธี = "หลังจาก" pointcut-ref = "pointcut"/> <aop: วิธีการกลับมา = "fternreturning" pointcut-ref = "pointcut" <AOP: รอบ ๆ วิธี = "รอบ" pointcut-ref = "pointcut"/> </aop: แง่มุม> </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: วิธีการถูกสกัดกั้นโดยคลาสหนึ่งด้าน
เมื่อวิธีการถูกสกัดกั้นเพียงด้านเดียวในลำดับใดคำแนะนำที่แตกต่างกันในด้านนี้ดำเนินการ? โปรดดู:
เพิ่มคลาส Pointcut
จุดนี้ใช้เพื่อสกัดกั้นวิธีการทั้งหมดในทุกคลาสภายใต้แพ็คเกจทดสอบ
การทดสอบแพ็คเกจ; นำเข้า org.aspectj.lang.annotation.pointcut; Public Class PointCuts {@PointCut (value = "ภายใน (ทดสอบ.*)") โมฆะสาธารณะ AOPDEMO () {}}เพิ่มคลาสต่างๆ
คำแนะนำในชั้นเรียนนี้จะใช้ pointcut ด้านบน โปรดดูแอตทริบิวต์ค่าของแต่ละคำแนะนำเมื่อใช้งาน
การทดสอบแพ็คเกจ; นำเข้า org.aspectj.lang.joinpoint; นำเข้า org.aspectj.lang.proceedingjoinpoint; นำเข้า org.aspectj.lang.annotation.*; นำเข้า org.springframework.stereotype.Component; joinPoint) {system.out.println ("[ภาพ 1] ก่อนคำแนะนำ"); } @Around (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะรอบ ๆ (ดำเนินการ joinpoint pjp) โยนได้ {system.out.println ("[ภาพ 1] รอบคำแนะนำ 1"); pjp.proceed (); System.out.println ("[ภาพ 1] รอบคำแนะนำ 2"); } @afterreturning (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะ ackreturning (joinpoint joinpoint) {system.out.println ("[ภาพ 1] คำแนะนำการส่งคืน"); } @afterthrowing (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะหลังการยืน (joinpoint joinpoint) {system.out.println ("[ภาพ 1] คำแนะนำหลังการเสแสร้ง"); } @after (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะหลังจาก (joinpoint joinpoint) {system.out.println ("[ภาพ 1] คำแนะนำหลังการยก"); } @after (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะหลังจาก (joinpoint joinpoint) {system.out.println ("[ภาพ 1] หลังจากคำแนะนำ"); -เพิ่มคอนโทรลเลอร์ทดสอบ
เพิ่มคอนโทรลเลอร์สำหรับการทดสอบ มีเพียงวิธีเดียวในคอนโทรลเลอร์นี้ แต่มันจะจัดการแตกต่างกันตามค่าพารามิเตอร์: หนึ่งคือการส่งคืนวัตถุตามปกติและอื่น ๆ คือการโยนข้อยกเว้น (เพราะเราต้องการทดสอบคำแนะนำ @afterthrowing)
การทดสอบแพ็คเกจ; Import Test.exception.testexception; นำเข้า org.springframework.http.httpstatus; นำเข้า org.springframework.web.bind.annotation*;@restcontroller@requestmapping (ค่า = "/aop") @RequestMapping (value = "/test", method = requestMethod.get) การทดสอบผลลัพธ์สาธารณะ (@RequestParam boolean throlhException) {// กรณีที่ 1 ถ้า (throwexception) {system.out.println ("โยนข้อยกเว้น"); โยน testexception ใหม่ ("เยาะเย้ยข้อยกเว้นเซิร์ฟเวอร์"); } // กรณีที่ 2 System.out.println ("ทดสอบตกลง"); ส่งคืนผลลัพธ์ใหม่ () {{this.setId (111); this.setName ("เยาะเย้ยผลลัพธ์"); - } ผลลัพธ์คลาสคงที่ระดับสาธารณะ {ID INT ส่วนตัว; ชื่อสตริงส่วนตัว; สาธารณะ int getId () {return id; } โมฆะสาธารณะ setId (int id) {this.id = id; } สตริงสาธารณะ getName () {ชื่อคืน; } โมฆะสาธารณะ setName (ชื่อสตริง) {this.name = name; -ทดสอบสถานการณ์ปกติ
ป้อน URL ต่อไปนี้โดยตรงในเบราว์เซอร์และป้อน: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false 1
เราจะเห็นผลลัพธ์ผลลัพธ์:
[ภาพที่ 1] เกี่ยวกับคำแนะนำ 1 [แง่มุม 1] ก่อนคำแนะนำตกลง [แง่มุม 1] เกี่ยวกับคำแนะนำ 2 [ภาพ 1] หลังจากคำแนะนำ [ภาพ 1] คำแนะนำในการตอบกลับ
ทดสอบข้อยกเว้น
ป้อน URL ต่อไปนี้โดยตรงในเบราว์เซอร์และกด Enter: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true 1
เราจะเห็นผลลัพธ์ผลลัพธ์:
[ภาพที่ 1] เกี่ยวกับคำแนะนำ 1 [แง่มุม 1] ก่อนที่จะมีข้อยกเว้น [แง่มุม 1] หลังจากคำแนะนำ [แง่มุม 1] คำแนะนำหลังการเทียม
สรุปแล้ว
เมื่อวิธีการถูกสกัดกั้นโดยคลาสหนึ่งด้านคำแนะนำภายในคลาส ASPICE จะถูกดำเนินการตามลำดับต่อไปนี้:
สถานการณ์ปกติ:
ข้อยกเว้น:
กรณีที่ 2: วิธีการเดียวกันถูกสกัดกั้นโดยคลาสต่างๆ
นี่คือตัวอย่างที่ถูกสกัดกั้นโดยสองคลาส
ในบางกรณีสำหรับสองคลาสที่แตกต่างกันโดยไม่คำนึงว่าคำแนะนำของพวกเขาใช้ pointcut เดียวกันหรือ pointcuts ที่แตกต่างกันมันอาจทำให้วิธีเดียวกันถูกสกัดกั้นโดยคลาสหลายด้าน ดังนั้นในกรณีนี้คำแนะนำในคลาสต่างๆเหล่านี้จะดำเนินการในลำดับใด โปรดดู:
คลาส Pointcut ยังคงไม่เปลี่ยนแปลง
เพิ่มคลาสมุมมองใหม่
การทดสอบแพ็คเกจ; นำเข้า org.aspectj.lang.joinpoint; นำเข้า org.aspectj.lang.proceedingjoinpoint; นำเข้า org.aspectj.lang.annotation.*; นำเข้า org.springframework.stereotype.Component; joinPoint) {system.out.println ("[ภาพ 2] ก่อนคำแนะนำ"); } @Around (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะรอบ ๆ (ดำเนินการ joinpoint pjp) โยนได้ {system.out.println ("[ภาพ 2] รอบคำแนะนำ 1"); pjp.proceed (); System.out.println ("[ภาพ 2] รอบคำแนะนำ 2"); } @afterreturning (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะ ackreturning (joinpoint joinpoint) {system.out.println ("[ASPASS 2] คำแนะนำการส่งคืน"); } @afterthrowing (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะหลังการยืน (joinpoint joinpoint) {system.out.println ("[ASPACT2] คำแนะนำหลังการเสแสร้ง"); } @after (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะหลังจาก (joinpoint joinpoint) {system.out.println ("[ภาพ 2] คำแนะนำหลังการยก"); } @after (value = "test.pointcuts.aopdemo ()") โมฆะสาธารณะหลังจาก (joinpoint joinpoint) {system.out.println ("[ภาพ 2] หลังจากแนะนำ"); -คอนโทรลเลอร์ทดสอบยังไม่เปลี่ยนแปลง
ยังคงใช้คอนโทรลเลอร์ด้านบน แต่ตอนนี้ทั้งภาพ 1 และ ASPACT2 สกัดกั้นวิธีการในคอนโทรลเลอร์
ทดสอบต่อไปด้านล่าง!
ทดสอบสถานการณ์ปกติ
ป้อน URL ต่อไปนี้โดยตรงในเบราว์เซอร์และป้อน: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false 1
เราจะเห็นผลลัพธ์ผลลัพธ์:
[ASPACT2] เกี่ยวกับคำแนะนำ 1 [ASPASSION] ก่อนคำแนะนำ [แง่มุม 1] เกี่ยวกับคำแนะนำ 1 [แง่มุม 1] ก่อนที่จะให้คำแนะนำตกลง [ภาพ 1] เกี่ยวกับคำแนะนำ 2 [แง่มุม 1] หลังจากคำแนะนำ [ภาพที่ 1] คำแนะนำในการตอบกลับ
แต่ในเวลานี้ฉันไม่สามารถสรุปได้ว่าแง่มุม 2 จะถูกดำเนินการอย่างแน่นอนก่อนแง่มุม 1
ไม่เชื่อ? คุณรีสตาร์ทเซิร์ฟเวอร์และลองอีกครั้งบางทีคุณอาจเห็นผลลัพธ์การดำเนินการต่อไปนี้:
[ภาพที่ 1] เกี่ยวกับคำแนะนำ 1 [ภาพที่ 1] ก่อนคำแนะนำ [ด้าน 2] เกี่ยวกับคำแนะนำ 1 [แง่มุม 2] ก่อนที่จะให้คำแนะนำตกลง [ภาพ 2] เกี่ยวกับคำแนะนำ 2 [แง่มุม 2] หลังจากคำแนะนำ [ภาพ 2] คำแนะนำที่ดีขึ้น
นั่นคือในกรณีนี้ไม่ทราบคำสั่งการดำเนินการของ APPECT1 และ ASPECT2 แล้วจะแก้ปัญหาได้อย่างไร? ไม่รีบร้อนการแก้ปัญหาจะได้รับด้านล่าง
ทดสอบข้อยกเว้น
ป้อน URL ต่อไปนี้โดยตรงในเบราว์เซอร์และกด Enter: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true 1
เราจะเห็นผลลัพธ์ผลลัพธ์:
[ASPASSION] เกี่ยวกับคำแนะนำ 1 [ASPASSION] ก่อนคำแนะนำ [ภาพ 1] เกี่ยวกับคำแนะนำ 1 [ASPASSION] ก่อนที่จะก้าวไปข้างหน้าข้อยกเว้น [แง่มุม 1] หลังจากโยนคำแนะนำ [ASPASSION] หลังจากโยนคำแนะนำ
ในทำนองเดียวกันถ้าคุณรีสตาร์ทเซิร์ฟเวอร์แล้วทดสอบอีกครั้งคุณอาจเห็นผลลัพธ์ต่อไปนี้:
[ภาพที่ 1] เกี่ยวกับคำแนะนำ 1 [แง่มุม 1] ก่อนคำแนะนำ [ด้าน 2] เกี่ยวกับคำแนะนำ 1 [แง่มุม 2] ก่อนที่จะก้าวไปข้างหน้าข้อยกเว้น [แง่มุม 2] คำแนะนำหลังการเทียม [ภาพ 1] คำแนะนำหลังการยก
กล่าวคือในทำนองเดียวกันลำดับการดำเนินการของ APPECT1 และ APISICE 2 ก็ไม่ได้ระบุไว้ในสถานการณ์พิเศษ
ดังนั้นในกรณีที่ 2 คุณจะระบุลำดับการดำเนินการของแต่ละด้านได้อย่างไร?
มีสองวิธี:
ไม่ว่าจะใช้วิธีใดก็ตาม
ตัวอย่างเช่นเราเพิ่มคำอธิบายประกอบ @order สำหรับ APSECT1 และ ASPASS2 ตามลำดับดังนี้:
@Order (5)@Component@AspectPublic Class Spection1 {// ... }@order (6)@component@AspectPublic Class APSICE 2 {// ... } หลังจากการดัดแปลงนี้สามารถมั่นใจได้ว่าในกรณีใด ๆ คำแนะนำในแง่มุม 1 จะถูกดำเนินการเสมอก่อนที่จะมีคำแนะนำในด้าน 2 ดังที่แสดงในรูปด้านล่าง:
บันทึก
หากมีการกำหนดคำแนะนำที่เหมือนกันสองประการสำหรับ pointcut เดียวกัน (ตัวอย่างเช่นสอง @Before) จะถูกกำหนดลำดับการดำเนินการของคำแนะนำทั้งสองนี้ไม่สามารถกำหนดได้แม้ว่าคุณจะเพิ่มคำอธิบายประกอบ @order ลงในคำแนะนำทั้งสองนี้มันจะไม่ทำงาน จำไว้ว่าสิ่งนี้
สำหรับคำแนะนำ @Around ไม่ว่าจะมีค่าส่งคืนหรือไม่ก็จะต้องเรียก pjp.proceed () ภายในวิธีการ; มิฉะนั้นอินเทอร์เฟซในคอนโทรลเลอร์จะไม่ถูกดำเนินการซึ่งจะทำให้คำแนะนำ @Before ไม่ถูกเรียกใช้ ตัวอย่างเช่นเราสมมติว่าภายใต้สถานการณ์ปกติคำสั่งการดำเนินการคือ "APISICE2 -> APSECT1 -> Controller" ถ้าเราลบ pjp.proceed (); ใน @around ในแง่มุม 1 จากนั้นผลลัพธ์ที่เราเห็นจะเป็น:
[ASPASSION] เกี่ยวกับคำแนะนำ 1 [ASPASSION] ก่อนคำแนะนำ [ภาพ 1] เกี่ยวกับคำแนะนำ 1 [ASPASSION] รอบ ๆ คำแนะนำ 2 [ASPASSION] หลังจากคำแนะนำ [แง่มุม 1] คำแนะนำในการตอบกลับ [ASPASSION2] รอบ ๆ คำแนะนำ 2
จากผลลัพธ์เราสามารถพบได้ว่าอินเทอร์เฟซในคอนโทรลเลอร์ยังไม่ถูกดำเนินการและ @beforeadvice ในแง่มุม 1 ยังไม่ได้ดำเนินการเช่นกัน
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น