Spring?Boot?Aop執(zhí)行順序深入探究
Spring Boot Aop 執(zhí)行順序
1. 概述
在 spring boot 項目中,使用 aop 增強(qiáng),不僅可以很優(yōu)雅地擴(kuò)展功能,還可以讓一寫多用,避免寫重復(fù)代碼,例如:記錄接口耗時,記錄接口日志,接口權(quán)限,等等。所以,在項目中學(xué)習(xí)并使用 aop ,是十分必要的。然而,當(dāng)我們在一個接口中使用多個 aop,時,就需要注意他們的執(zhí)行順序了。那么,它們的執(zhí)行順序是怎樣的呢?如果不把這個問題搞明白,那我們的程序就不可控,這是不允許的,這就是我們今天要討論的問題。
2. 實現(xiàn) AOP
2.1 通過注解實現(xiàn) AOP
MyAop:
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAop { }
MyAspect:
@Aspect @Component public class MyAspect { @Around("@annotation(aop)") public Object around(ProceedingJoinPoint joinPoint, MyAop aop) throws Throwable { return joinPoint.proceed(); } }
SampleController#myApi:
@RestController @RequestMapping("/sample") public class SampleController { @MyAop @RequestMapping("/my-api") public String myApi() { return "success"; } }
這樣,我們就通過使用注解的方式實現(xiàn)了 AOP 。
2.2 通過掃描包
比如,我們有這樣一個接口 SampleController#myApi2:
@RestController @RequestMapping("/sample") public class SampleController { @RequestMapping("/my-api2") public String myApi2() { return "success"; } }
我們可以使用包掃描的方式進(jìn)行攔截:
@Aspect @Component public class My2Aspect { @Around("execution(* com.fengwenyi.demo.springboot.aop.controller.SampleController.myApi2(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { return joinPoint.proceed(); } }
這樣,我們也就通過使用包掃描的方式實現(xiàn)了 AOP 。
3. 多個 AOP
3.1 分析
先提一個疑問:多個AOP注解,執(zhí)行順序是怎么樣的呢?如何設(shè)置執(zhí)行順序呢?
比如,APP 請求我們的 API 接口,在請求到達(dá) API 接口之前,可以先執(zhí)行 AOP1,在執(zhí)行 AOP2,并且順序不能變,如下圖:
我們再拆解一下實際內(nèi)部執(zhí)行邏輯。
請求:請求先進(jìn)入到 AOP1,再進(jìn)入到 AOP2,最后到達(dá) API。
返回:執(zhí)行完 API,再回到 AOP2,最后回到 AOP1。
如下圖:
因為我們用的是 Around,先進(jìn)入Aop1,再進(jìn)入到aop2,然后執(zhí)行api,執(zhí)行完以后,再返回到 aop2,最后返回aop1。
3.2 代碼實現(xiàn)
MyFirstAop:
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyFirstAop { }
MyFirstAspect:
@Slf4j @Aspect @Component @Order(100002) public class MyFirstAspect { @Around("@annotation(aop)") public Object around(ProceedingJoinPoint joinPoint, MyFirstAop aop) throws Throwable { log.info("MyFirstAspect#around execute start"); try { return joinPoint.proceed(); } finally { log.info("MyFirstAspect#around execute end"); } } }
MySecondAop:
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MySecondAop { }
MySecondAspect:
@Slf4j @Aspect @Component @Order(100003) public class MySecondAspect { @Around("@annotation(aop)") public Object around(ProceedingJoinPoint joinPoint, MySecondAop aop) throws Throwable { log.info("MySecondAspect#around execute start"); try { return joinPoint.proceed(); } finally { log.info("MySecondAspect#around execute end"); } } }
SampleController#aopOrder:
@RestController @RequestMapping("/sample") public class SampleController { @MySecondAop @MyFirstAop @RequestMapping("/aop-order") public String aopOrder() { return "aopOrder"; } }
通過設(shè)定 Order 值,指定 AOP 執(zhí)行順序,與我們的期望一致。
好了,今天的分享就到這里了,源碼:demo-spring-boot-aop。
以上就是Spring Boot Aop 執(zhí)行順序的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot Aop 執(zhí)行順序的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解使用spring boot admin監(jiān)控spring cloud應(yīng)用程序
這篇文章主要介紹了詳解使用spring boot admin監(jiān)控spring cloud應(yīng)用程序,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05@RequestParam?和@RequestBody注解的區(qū)別解析
在 Spring MVC 中,我們可以使用 @RequestParam 和 @RequestBody 來獲取請求參數(shù),但它們在用法和作用上有一些區(qū)別,這篇文章主要介紹了@RequestParam?和@RequestBody注解的區(qū)別,需要的朋友可以參考下2023-06-06解讀Jvm的內(nèi)存結(jié)構(gòu)與GC及jvm參數(shù)調(diào)優(yōu)
這篇文章主要介紹了解讀Jvm的內(nèi)存結(jié)構(gòu)與GC及jvm參數(shù)調(diào)優(yōu)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05