Spring AOP失效的常見場(chǎng)景分析
前言
Spring的AOP(面向切面編程)是一種強(qiáng)大的技術(shù),用于在應(yīng)用程序中實(shí)現(xiàn)橫切關(guān)注點(diǎn)的模塊化。雖然Spring的AOP在大多數(shù)情況下都是有效的,但在某些場(chǎng)景下可能會(huì)失效。下面來分析Spring AOP失效的常見場(chǎng)景
首先,Spring的AOP其實(shí)是通過動(dòng)態(tài)代理實(shí)現(xiàn)的,所以,想要讓AOP生效,前提必須是動(dòng)態(tài)代理生效,并且可以調(diào)用到代理對(duì)象的方法
1.非Spring管理的對(duì)象
Spring的AOP只能攔截由Spring容器管理的Bean對(duì)象。如果您使用了非受Spring管理的對(duì)象,則AOP將無法對(duì)其進(jìn)行攔截。
2.同一個(gè)Bean內(nèi)部方法調(diào)用
如果一個(gè)Bean內(nèi)部的方法直接調(diào)用同一個(gè)Bean內(nèi)部的另一個(gè)方法,AOP將無法攔截這個(gè)內(nèi)部方法調(diào)用。因?yàn)锳OP是基于代理的,只有通過代理對(duì)象才能觸發(fā)AOP攔截。
@Component public class MyBean { public void method1() { System.out.println("Inside method1"); method2(); // 直接調(diào)用同一個(gè) Bean 內(nèi)部的另一個(gè)方法 } public void method2() { System.out.println("Inside method2"); } }
假設(shè)我們有一個(gè)名為 MyBean
的類,其中包含了兩個(gè)方法 method1()
和 method2()
。在 method1()
中,直接調(diào)用了 method2()
方法。
現(xiàn)在,讓我們創(chuàng)建一個(gè)切面來攔截 method1()
的執(zhí)行,并打印一些日志信息:
@Aspect @Component public class MyAspect { @Before("execution(* com.example.MyBean.method1())") public void beforeMethod1() { System.out.println("Before method1 execution"); } }
上述切面使用 @Before
注解來定義了一個(gè)前置通知,在執(zhí)行 MyBean
類的 method1()
方法之前被觸發(fā)。
然后,我們?cè)?Spring 應(yīng)用程序中使用這兩個(gè)組件:
@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); MyBean myBean = ApplicationContext.getBean(MyBean.class); myBean.method1(); } }
當(dāng)我們運(yùn)行應(yīng)用程序時(shí),我們會(huì)發(fā)現(xiàn) "Before method1 execution" 這條日志信息被打印出來,但是 "Inside method2" 這條日志信息卻沒有被打印出來。這是因?yàn)?AOP 無法攔截 method2()
的直接調(diào)用,而只能攔截通過代理對(duì)象觸發(fā)的方法調(diào)用。
3.靜態(tài)方法
Spring的AOP只能攔截非靜態(tài)方法。如果您嘗試攔截靜態(tài)方法,AOP將無法生效。
4.final方法
AOP無法攔截final方法。final方法是不可重寫的,因此AOP無法生成代理對(duì)象來攔截這些方法。
直接在對(duì)象內(nèi)部調(diào)用方法:如果您直接在對(duì)象內(nèi)部調(diào)用方法而不通過代理對(duì)象,AOP將無法攔截。因此,建議始終通過代理對(duì)象調(diào)用方法以確保AOP的生效。
5.異步方法
對(duì)于使用Spring的異步特性(如@Async注解)的方法,AOP攔截器可能無法正常工作。這是因?yàn)楫惒椒椒ㄔ谶\(yùn)行時(shí)會(huì)創(chuàng)建新的線程或使用線程池,AOP攔截器無法跟蹤到這些新線程中的方法調(diào)用。
總結(jié)
以下幾種情況會(huì)導(dǎo)致AOP失效:
非Spring管理的對(duì)象
私有方法調(diào)用
靜態(tài)方法調(diào)用
final方法調(diào)用
類內(nèi)部自調(diào)用
內(nèi)部類方法調(diào)用
異步方法
以上就是Spring AOP失效的常見場(chǎng)景分析的詳細(xì)內(nèi)容,更多關(guān)于Spring AOP失效場(chǎng)景的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot中@RestControllerAdvice注解實(shí)現(xiàn)全局異常處理類
這篇文章主要介紹了SpringBoot中@RestControllerAdvice注解全局異常處理類,springboot中使用@RestControllerAdvice注解,完成優(yōu)雅的全局異常處理類,可以針對(duì)所有異常類型先進(jìn)行通用處理后再對(duì)特定異常類型進(jìn)行不同的處理操作,需要的朋友可以參考下2024-01-01springboot?bootstrap.yml?nacos配置中心問題
這篇文章主要介紹了springboot?bootstrap.yml?nacos配置中心問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03Nacos啟動(dòng)出現(xiàn)failed to req API:/nacos/v1/ns/insta
這篇文章主要介紹了Nacos啟動(dòng)出現(xiàn)failed to req API:/nacos/v1/ns/instance after all servers問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08使用Spring Boot快速構(gòu)建基于SQLite數(shù)據(jù)源的應(yīng)用
為了提供一個(gè)單包易部署的服務(wù)器應(yīng)用,考慮使用Spring Boot,因?yàn)槠浼闪薃pache Tomcat,易于運(yùn)行,免去絕大部分了服務(wù)器配置的步驟2017-08-08在Spring boot的項(xiàng)目中使用Junit進(jìn)行單體測(cè)試
今天小編就為大家分享一篇關(guān)于spring boot使用Junit進(jìn)行測(cè)試,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12java實(shí)現(xiàn)圖書館管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)圖書館管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10SpringBoot?MP簡(jiǎn)單的分頁查詢測(cè)試實(shí)現(xiàn)步驟分解
好久沒水后端的東西了,最近在做vue項(xiàng)目寫前端的代碼,所以cloud也停進(jìn)度了,吃完飯突然記得我沒有在博客里寫分頁的東西,雖然項(xiàng)目中用到了,但是沒有拎出來,這里就拎出來看看2023-04-04SpringBoot如何配置MySQL和Oracl雙數(shù)據(jù)源(Mybatis)
這篇文章主要介紹了SpringBoot如何配置MySQL和Oracl雙數(shù)據(jù)源(Mybatis)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03