1. บทนำ
ในระหว่างกระบวนการพัฒนาเรามักจะต้องเขียนตัวอย่างมากมาย:
@getMapping ("/id/get") ผลลัพธ์สาธารณะ getById (string id) พ่นข้อยกเว้น {log.info ("พารามิเตอร์คำขอคือ:"+id); ตรวจสอบ (ใหม่ Verifyparam ("ID แผนก", id)); ผลลัพธ์ผลลัพธ์ = ผลลัพธ์ใหม่ ("ได้รับสำเร็จผ่าน ID!", Service.QueryById (ID)); log.info ("ข้อความส่งคืนคือ:"+result.toString ()); ผลการกลับมา; -พารามิเตอร์การร้องขอการพิมพ์และพารามิเตอร์ส่งคืนและการดำเนินการเหล่านี้มีอยู่ในแต่ละวิธีทำให้รหัสของเราซ้ำซ้อนมากขึ้น ด้วยเหตุผลนี้เราสามารถใช้พร็อกซีแบบไดนามิกเพื่อใช้พารามิเตอร์การพิมพ์และพิมพ์ข้อความส่งคืนเป็นส่วนและใช้นิพจน์การตัดจุดเพื่อตัดเป็นแต่ละวิธี
2. ขั้นตอน
1. แนะนำการพึ่งพาที่เกี่ยวข้องกับ AOP:
<!-การพึ่งพาที่เกี่ยวข้องกับ AOP-> <การพึ่งพา> <roupId> org.springframework.boot </groupid> <ratifactid> Spring-Boot-Starter-Aop </artifactid>
หลังจากแนะนำการพึ่งพาสปริง-AOP จะโหลดการพึ่งพาที่ต้องการ ฤดูใบไม้ผลิใช้ APISTICJ โดยค่าเริ่มต้นเพื่อใช้การแจ้งเตือน
ในหมู่พวกเขา spectionjweaver.jar มีไฟล์ที่วิเคราะห์การแสดงออกของจุดตัด การพึ่งพานี้จำเป็นเมื่อใช้การแสดงออกของจุดเพื่อจัดการธุรกรรม
2. การกำหนดค่า:
1) สร้างคลาสการกำหนดค่า:
/*** @function คำอธิบาย: คลาส AOP ที่ใช้สำหรับการดำเนินการเลเยอร์คอนโทรลเลอร์* @author Administrator*/ @Component // จัดการวัตถุเพื่อสปริงสำหรับการจัดการ @Aspect // เป็นตัวแทนคลาสนี้
คำอธิบายประกอบ @Aspect แสดงให้เห็นว่ามันเป็นคลาสการจัดการด้านที่สามารถกำหนดนิพจน์จุดตัดได้และกรอบการทำงานของ ASPECTJ จะแยกวิเคราะห์มัน
2) กำหนดนิพจน์จุดตัด:
@PointCut ("การดำเนินการ (สาธารณะ*com.hzt.Manage.*. web.controller ..*.*(.. ))") // pointcut expression public Public Privilege () {}โดยที่ @pointcut หมายถึงวิธีนี้เป็นนิพจน์ที่ตัดจุด ค่าของมันคือนิพจน์ที่ตัดจุดซึ่งสามารถละเว้นค่าและรูปแบบคร่าวๆคือ:
@Annotation (รูปแบบนิพจน์แท็ก + นิพจน์)
สำหรับรูปแบบตัวบ่งชี้จุดตัดที่รองรับโดย Spring AOP มีดังนี้:
1. การดำเนินการ: จุดเชื่อมต่อที่ใช้เพื่อให้ตรงกับวิธีการดำเนินการ;
2. ภายใน: ใช้เพื่อให้ตรงกับการดำเนินการของวิธีการภายในประเภทที่ระบุ;
3. สิ่งนี้: วิธีการดำเนินการที่ใช้เพื่อจับคู่ประเภทวัตถุพร็อกซี AOP ปัจจุบัน; โปรดทราบว่าการจับคู่ประเภทของวัตถุพร็อกซี AOP ซึ่งอาจรวมถึงการแนะนำอินเทอร์เฟซและการจับคู่ประเภท
4. เป้าหมาย: วิธีการดำเนินการที่ใช้เพื่อจับคู่ประเภทวัตถุเป้าหมายปัจจุบัน; โปรดทราบว่าการจับคู่ประเภทของวัตถุเป้าหมายคือการจับคู่ประเภทเพื่อไม่รวมการแนะนำของอินเทอร์เฟซ
5. ARGS: วิธีการดำเนินการใช้เพื่อให้ตรงกับพารามิเตอร์ที่ส่งผ่านโดยวิธีการที่ดำเนินการในปัจจุบันเป็นประเภทที่ระบุ;
6. @WithIn: ใช้เพื่อจับคู่วิธีการค้างไว้ภายในประเภทคำอธิบายประกอบที่ระบุ;
7. @Target: วิธีการดำเนินการที่ใช้เพื่อให้ตรงกับประเภทวัตถุเป้าหมายปัจจุบันซึ่งวัตถุเป้าหมายถือคำอธิบายประกอบที่ระบุ;
8. @ARGS: ใช้เพื่อให้ตรงกับการดำเนินการของพารามิเตอร์ที่ส่งผ่านในวิธีการที่ดำเนินการในปัจจุบันซึ่งมีคำอธิบายประกอบที่ระบุ;
9. @Annotation: ใช้เพื่อให้ตรงกับวิธีการที่ดำเนินการในปัจจุบันมีคำอธิบายประกอบที่ระบุ;
10. ถั่ว: ส่วนขยายของสปริง AOP, APISICE J ไม่มีวิธีการดำเนินการสำหรับการจับคู่วัตถุถั่วที่มีชื่อเฉพาะ;
11. การอ้างอิง PointCut: หมายถึงการอ้างอิงถึงจุดเริ่มต้นการตั้งชื่ออื่น ๆ เฉพาะสไตล์ @ApectJ รองรับ แต่ไม่ใช่สไตล์สคีมา
ARGS กำหนดพารามิเตอร์เมื่อดำเนินการวิธีการนิพจน์จุดตัด:
@PointCut (value = "การดำเนินการ (สาธารณะ*com.hzt.Manage.*. web.controller ..*.*(.. )) && args (param)", argnames = "param") // pointcut public public1 (พารามิเตอร์สตริง) {} {}เรามุ่งเน้นไปที่การแสดงออกของจุดเชื่อมต่อของวิธีการดำเนินการและโครงสร้างคร่าวๆคือ:
การดำเนินการ (ตัวดัดแปลงรูปแบบ?
1. การจับคู่ Modifier (Modifier-Pattern?) (สามารถละเว้นได้)
2. การจับคู่ค่าส่งคืน (RET-type-pattern) สามารถแสดงค่าส่งคืนใด ๆ สำหรับ *เช่น (สตริง) แสดงเฉพาะการกรองจุดเริ่มต้นที่ส่งคืนประเภทสตริงชื่อคลาสของเส้นทางเต็ม ฯลฯ (ไม่สามารถละเว้นได้)
3. การประกาศประเภทรูปแบบ? ตัวอย่างเช่น *. การจัดการแสดงถึงแพ็คเกจระดับแรกเป็นแพ็คเกจโดยพลการและแพ็คเกจระดับที่สองเป็นชื่อของการจัดการ *.. จัดการแสดงถึงแพ็คเกจย่อยภายใต้แพ็คเกจจัดการทั้งหมด com .. *. Comtroller แสดงถึงแพ็คเกจคอนโทรลเลอร์ทั้งหมดภายใต้แพ็คเกจ Com ฯลฯ และ * หมายความว่าแพ็คเกจทั้งหมดตรงกับ (ไม่ละเว้น)
4. การจับคู่ชื่อเมธอด (ชื่อรูปแบบ) สามารถระบุชื่อวิธีหรือ * แทนทั้งหมดรับ * แสดงถึงวิธีการทั้งหมดที่เริ่มต้นด้วย GET หรือคุณสามารถระบุคำนำหน้า * GET แทนวิธีใด ๆ
5. การจับคู่พารามิเตอร์ ((param-pattern)) สามารถระบุประเภทพารามิเตอร์เฉพาะพารามิเตอร์หลายพารามิเตอร์จะถูกคั่นด้วย "," และแต่ละพารามิเตอร์สามารถเป็น "*" เพื่อให้ตรงกับประเภทของพารามิเตอร์ใด ๆ เช่น (สตริง) หมายถึงวิธีการจับคู่พารามิเตอร์สตริง (*, String) หมายถึงวิธีการจับคู่พารามิเตอร์สองพารามิเตอร์พารามิเตอร์แรกสามารถเป็นประเภทใดก็ได้และพารามิเตอร์ที่สองเป็นประเภทสตริง (.. ) สามารถใช้เพื่อแสดงพารามิเตอร์ใด ๆ (ไม่ละเว้น)
6. การจับคู่ประเภทข้อยกเว้น (phrows-pattern?)
3. กำหนดวิธีการ FaceT
@Around ("Privilege ()") วัตถุสาธารณะรอบ ๆ (ดำเนินการ joinpoint pjd) โยน throwable {// รับเมธอดชื่อสตริง classname = pjd.getSignature (). getClass (). getName (); // รับเมธอดวิธีการเรียกใช้เมธอด name = pjd.getSignature (). getName (); / ** การพิมพ์บันทึกการเริ่มต้นการพิมพ์*/ logger log = loggerFactory.getLogger (className); // กำหนดผลลัพธ์ของวัตถุพารามิเตอร์การส่งคืน = null; // บันทึกเวลาเริ่มต้นยาว = System.currentTimeMillis (); // รับเมธอดพารามิเตอร์วัตถุ [] args = pjd.getargs (); String params = "พารามิเตอร์คำขอ front-end คือ:"; // รับการรวบรวมพารามิเตอร์การร้องขอและ Traverse และ Splice สำหรับ (วัตถุวัตถุ: args) {params + = object.toString () + ","; } params = params.substring (0, params.length () - 1); // พิมพ์พารามิเตอร์พารามิเตอร์การร้องขอ log.info (className + "class" + methodName + "" + params); // ดำเนินการตามวิธีการเป้าหมายผลลัพธ์ = pjd.proceed (); // พิมพ์บันทึกข้อความส่งคืน INFO ("วิธีการส่งคืนข้อความเป็น:" + (ผลลัพธ์ผลลัพธ์ของผลลัพธ์? (ผลลัพธ์) ผลลัพธ์: ผลลัพธ์)); // รับ log.info (MethodName + "เวลาดำเนินการวิธีการคือ:" + (System.currentTimeMillis () - เริ่มต้น)); ผลการกลับมา; -5. @Around Surround Notification ดังที่แสดงในรหัสด้านบนมันเป็นการแจ้งเตือนรอบทิศทางซึ่งมีพารามิเตอร์การดำเนินการ joinpoint
โดยที่ pjd.proceed (); วิธีการแสดงถึงการดำเนินการของวิธีเป้าหมายและรับค่าส่งคืนของประเภทวัตถุ เราสามารถประมวลผลค่าคืนได้เช่นการประมวลผลการตกแต่ง ฯลฯ
ค่าของผลตอบแทนเป็นผลมาจากการดำเนินการวิธีการ ในรหัสข้างต้นก่อนได้รับชื่อคลาสชื่อวิธีพารามิเตอร์วิธีการขอเมธอด ฯลฯ ทำการพิมพ์ประกบและบันทึกเวลาเริ่มต้นของการดำเนินการวิธีการและพิมพ์ลงในบันทึก
จากนั้นดำเนินการวิธีการรับผลการส่งคืนวิธีการพิมพ์เวลาดำเนินการและผลการดำเนินการ
ในที่สุดผลการดำเนินการจะถูกส่งกลับ นั่นคือการเข้ารหัสส่วน AOP ของข้อความคำขอและข้อความส่งคืนเสร็จสมบูรณ์
โดยที่ @around แสดงถึงวิธีการแจ้งเตือนโดยรอบมันมีประเภทต่อไปนี้:
1. @Before การแจ้งเตือนล่วงหน้าซึ่งมีพารามิเตอร์การร้องขอการเข้าร่วมซึ่งใช้เพื่อเชื่อมต่อรายละเอียดการเชื่อมต่อของจุดเชื่อมต่อปัจจุบันโดยทั่วไปรวมถึงชื่อวิธีและค่าพารามิเตอร์ Method Body จะดำเนินการก่อนที่จะดำเนินการวิธีการและพารามิเตอร์วิธีการไม่สามารถเปลี่ยนแปลงได้และไม่สามารถเปลี่ยนผลลัพธ์การดำเนินการของวิธีการ
@Before (value = "privilege ()") โมฆะสาธารณะก่อน (joinpoint joinpoint) {}2. การแจ้งเตือนโพสต์ @after: การแจ้งเตือนว่าการดำเนินการจะดำเนินการโดยไม่คำนึงถึงว่ามีข้อยกเว้นเกิดขึ้นหลังจากวิธีการเป้าหมายถูกดำเนินการ ในการโพสต์การแจ้งเตือนผลการดำเนินการของวิธีเป้าหมายไม่สามารถเข้าถึงได้ (เนื่องจากข้อยกเว้นอาจเกิดขึ้น) และผลการดำเนินการของวิธีการไม่สามารถเปลี่ยนแปลงได้
@Before (value = "privilege ()") โมฆะสาธารณะหลังจาก (joinpoint joinpoint) {}3. @afterreturning ส่งคืนการแจ้งเตือน การแจ้งเตือนที่ดำเนินการเฉพาะเมื่อวิธีการเป้าหมายถูกดำเนินการเหมือนกับวิธีการโพสต์ที่จัดขึ้น มันสามารถเข้าถึงผลลัพธ์การดำเนินการวิธีการ (เนื่องจากการดำเนินการปกติ) และรายละเอียดการเชื่อมต่อของวิธีการ แต่ไม่สามารถเปลี่ยนผลลัพธ์การดำเนินการวิธีการ
@afterReturning (value = "privilege ()") โมฆะสาธารณะการส่งคืน (joinpoint joinpoint, ผลลัพธ์วัตถุ) {}ค่าส่งคืนที่เก็บไว้ในผลลัพธ์คือวิธีการ
4. การแจ้งเตือนข้อยกเว้น @afterthrowing: รหัสที่จะดำเนินการเฉพาะเมื่อมีข้อยกเว้นเกิดขึ้นในวิธีเป้าหมาย แอตทริบิวต์การขว้างปาแสดงถึงข้อยกเว้นที่โยนระหว่างการดำเนินการของร่างกายวิธีการและค่าของมันจะต้องสอดคล้องกับค่าของข้อยกเว้นในวิธีการ
@afterthrowing (value = "privilege ()", การขว้าง = "ex") โมฆะสาธารณะเกิน (joinpoint joinpoint, exception ex) {}3. ทดสอบ
เขียนวิธีการควบคุม
@restcontroller@requestmapping ("/api/v1/dept") คลาสสาธารณะ DeptController ขยาย basecontroller {/** คลาสการบันทึก*/logger ส่วนตัวบันทึก = loggerFactory.getLogger (getClass ()); / ** บริการของฉันเอง*/ @autowired Private Deptservice Service; /*** @function คำอธิบาย: วิธีการสอบถามเนื้อหาแผนกตาม ID* @return dept*/@getMapping ("/id/get") ผลลัพธ์สาธารณะ getById (String id) โยนข้อยกเว้น {ตรวจสอบ (ใหม่ Verifyparam ("ID แผนก", ID)); ส่งคืนผลลัพธ์ใหม่ ("ได้รับสำเร็จผ่าน ID!", Service.QueryById (ID)); -ด้วยวิธีนี้วิธีการในเลเยอร์คอนโทรลเลอร์ของเรานั้นกระชับอย่างมาก
ผลการทดสอบ:
2018-04-10 22: 59: 27.468 ข้อมูล 1460 --- [NIO-8088-Exec-5] nproceedingjoinpoint $ methodSignatureImpl: พารามิเตอร์คำขอ front-end ของ getByid คือ: 22
2018-04-10 22: 59: 27.470 ข้อมูล 1460 --- [NIO-8088-Exec-5] nproceedingJoinPoint $ methodSignatureimpl: วิธีการส่งคืนข้อความเป็น: result [result_code = suc, result_message = ประสบความสำเร็จ createTime = thu 19 เม.ย. 23:38:37 CST 2018, edittime = null]]
2018-04-10 22: 59: 27.470 ข้อมูล 1460 --- [NIO-8088-Exec-5] nproceedingJoinPoint $ methodSignatureImpl: เวลาดำเนินการของวิธี getById คือ: 2
สิ่งนี้ช่วยให้คุณสามารถพิมพ์พารามิเตอร์คำขอส่งคืนผลลัพธ์เวลาดำเนินการ ฯลฯ ด้วยการพิมพ์ที่สง่างามกระชับและรัดกุม!