十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)SpringBoot中怎么使用面向切面編程,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)主營玉山網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,手機APP定制開發(fā),玉山h5重慶小程序開發(fā)搭建,玉山網(wǎng)站營銷推廣歡迎玉山等地區(qū)企業(yè)咨詢
一、什么是AOP?
AOP,面向切面編程,一句話說明,把一些公共的、和業(yè)務(wù)無關(guān)的功能性代碼抽取出來,在運行的時候動態(tài)的往業(yè)務(wù)方法上植入。利用 AOP 可以對業(yè)務(wù)邏輯的各個部分進行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
二、AOP常用場景:
事務(wù)開啟關(guān)閉控制
日志記錄
權(quán)限校驗
三、AOP 相關(guān)概念介紹:
Joinpoint(連接點):類里面可以被增強的方法即為連接點。例如,想要修改哪個方法的功能,那么該方法就是一個鏈接點。
Target(目標(biāo)對象):要增強的類成為 Target。
Pointcut(切入點):對 Jointpoint 進行攔截的定義即為切入點。例如,攔截所有以 insert 開始的方法,這個定義即為切入點。
Advice(通知):攔截到 Jointpoint 之后要做的事情就是通知。通知分為前置通知、后置通知、異常通知、最終通知和環(huán)繞通知。例如,前面說到的打印日志監(jiān)控就是通知。
Aspect(切面):即 Pointcut 和 Advice 的結(jié)合。
通知方法的幾種類型:
前置通知(Before advice):在某個連接點(Join point)之前執(zhí)行的通知,但這個通知不能阻止連接點的執(zhí)行(除非它拋出一個異常)。
后置通知(After(finally)advice):當(dāng)某個連接點(Join point)退出的時候執(zhí)行的通知(不論是正常返回還是發(fā)生異常退出)。
返回通知(After returning advice):在某個連接點(Join point)正常完成后執(zhí)行的通知。例如,一個方法沒有拋出任何異常正常返回。
異常通知(After throwing advice):在方法拋出異常后執(zhí)行的通知。
環(huán)繞通知(Around advice):包圍一個連接點(Join point)的通知,如方法調(diào)用。這是最強大的一種通知類型。環(huán)繞通知可以在方法前后完成自定義的行為。它也會選擇是否繼續(xù)執(zhí)行連接點或直接返回它們自己的返回值或拋出異常來結(jié)束執(zhí)行。
四、安裝配置
Spring Boot 在 Spring 的基礎(chǔ)上對 AOP 的配置提供了自動化配置解決方案,我們只需要修改 pom.xml 文件,添加 spring-boot-starter-aop 依賴即可。
org.springframework.boot spring-boot-starter-aop
五、編寫代碼
1、編寫controller
@RestController public class DemoController { @Autowired UserService userService; @GetMapping("/demo") public String demo(Integer id) { return userService.getUserById(id); } }
2、編寫service
@Service public class UserService { public String getUserById(Integer id) { System.out.println("getUserById(" + id + ")..."); // 等待2秒 try { Thread.sleep(2000); } catch(InterruptedException e) { e.printStackTrace(); } return "piao"; } }
3、編寫切面
注解說明:
(1)@Aspect 注解:表明這是一個切面類。
(2)@Pointcut 注解:表明這是一個切入點。
execution 中的第一個 * 表示方法返回任意值
第二個 * 表示 service 包下的任意類
第三個 * 表示類中的任意方法,括號中的兩個點表示方法參數(shù)任意,即這里描述的切入點為 service 包下所有類中的所有方法。
(3)@Before 注解:表示這是一個前置通知,該方法在目標(biāo)方法之前執(zhí)行。
通過 JoinPoint 參數(shù)可以獲取目標(biāo)方法的方法名、修飾符等信息。
(4)@After 注解:表示這是一個后置通知,該方法在目標(biāo)執(zhí)行之后執(zhí)行。
(5)@AfterReturning 注解:表示這是一個返回通知,在該方法中可以獲取目標(biāo)方法的返回值。
returning 參數(shù)是指返回值的變量名,對應(yīng)方法的參數(shù)。
注意:本樣例在方法參數(shù)中定義 result 的類型為 Object,表示目標(biāo)方法的返回值可以是任意類型。若 result 參數(shù)的類型為 Long,則該方法只能處理目標(biāo)方法返回值為 Long 的情況。
(6)@AfterThrowing 注解:表示這是一個異常通知,即當(dāng)目標(biāo)方法發(fā)生異常,該方法會被調(diào)用。
樣例中設(shè)置的異常類型為 Exception 表示所有的異常都會進入該方法中執(zhí)行。
若異常類型為 ArithmeticException 則表示只有目標(biāo)方法拋出的 ArithmeticException 異常才會進入該方法的處理。
(7) @Around 注解:表示這是一個環(huán)繞通知。環(huán)繞通知是所有通知里功能最為強大的通知,可以實現(xiàn)前置通知、后置通知、異常通知以及返回通知的功能。
目標(biāo)方法進入環(huán)繞通知后,通過調(diào)用 ProceedingJointPoint 對象的 proceed 方法使目標(biāo)方法繼續(xù)執(zhí)行,開發(fā)者可以在次修改目標(biāo)方法的執(zhí)行參數(shù)、返回值值,并且可以在此目標(biāo)方法的異常。
@Aspect @Component public class LogAspect { // 定義一個切入點 @Pointcut("execution(* com.example.demo.service.*.*(..))") public void pc1(){ } // 前置通知 @Before(value = "pc1()") public void before(JoinPoint jp) { String name = jp.getSignature().getName(); System.out.println(name + "方法開始執(zhí)行..."); } // 后置通知 @After(value = "pc1()") public void after(JoinPoint jp) { String name = jp.getSignature().getName(); System.out.println(name + "方法執(zhí)行結(jié)束..."); } // 返回通知 @AfterReturning(value = "pc1()", returning = "result") public void afterReturning(JoinPoint jp, Object result) { String name = jp.getSignature().getName(); System.out.println(name + "方法返回值為:" + result); } // 異常通知 @AfterThrowing(value = "pc1()", throwing = "e") public void afterThrowing(JoinPoint jp, Exception e) { String name = jp.getSignature().getName(); System.out.println(name + "方法拋異常了,異常是:" + e.getMessage()); } // 環(huán)繞通知 @Around("pc1()") public Object around(ProceedingJoinPoint pjp) throws Throwable { String name = pjp.getSignature().getName(); // 統(tǒng)計方法執(zhí)行時間 long start = System.currentTimeMillis(); Object result = pjp.proceed(); long end = System.currentTimeMillis(); System.out.println(name + "方法執(zhí)行時間為:" + (end - start) + " ms"); return result; } }
六、驗證結(jié)果
1、請求接口:http://127.0.0.1:8086/demo
2、查看控制臺信息:
上述就是小編為大家分享的SpringBoot中怎么使用面向切面編程了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。