Spring?Boot?Aop執(zhí)行順序深入探究
Spring Boot Aop 執(zhí)行順序
1. 概述
在 spring boot 項目中,使用 aop 增強,不僅可以很優(yōu)雅地擴展功能,還可以讓一寫多用,避免寫重復代碼,例如:記錄接口耗時,記錄接口日志,接口權限,等等。所以,在項目中學習并使用 aop ,是十分必要的。然而,當我們在一個接口中使用多個 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";
}
}我們可以使用包掃描的方式進行攔截:
@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í)行順序是怎么樣的呢?如何設置執(zhí)行順序呢?
比如,APP 請求我們的 API 接口,在請求到達 API 接口之前,可以先執(zhí)行 AOP1,在執(zhí)行 AOP2,并且順序不能變,如下圖:

我們再拆解一下實際內部執(zhí)行邏輯。
請求:請求先進入到 AOP1,再進入到 AOP2,最后到達 API。
返回:執(zhí)行完 API,再回到 AOP2,最后回到 AOP1。
如下圖:

因為我們用的是 Around,先進入Aop1,再進入到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";
}
}
通過設定 Order 值,指定 AOP 執(zhí)行順序,與我們的期望一致。
好了,今天的分享就到這里了,源碼:demo-spring-boot-aop。
以上就是Spring Boot Aop 執(zhí)行順序的詳細內容,更多關于Spring Boot Aop 執(zhí)行順序的資料請關注腳本之家其它相關文章!
相關文章
詳解使用spring boot admin監(jiān)控spring cloud應用程序
這篇文章主要介紹了詳解使用spring boot admin監(jiān)控spring cloud應用程序,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
@RequestParam?和@RequestBody注解的區(qū)別解析
在 Spring MVC 中,我們可以使用 @RequestParam 和 @RequestBody 來獲取請求參數(shù),但它們在用法和作用上有一些區(qū)別,這篇文章主要介紹了@RequestParam?和@RequestBody注解的區(qū)別,需要的朋友可以參考下2023-06-06
解讀Jvm的內存結構與GC及jvm參數(shù)調優(yōu)
這篇文章主要介紹了解讀Jvm的內存結構與GC及jvm參數(shù)調優(yōu)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05

