SpringBoot @Async注解失效分析


 有時候在使用的過程中@Async注解會失效(原因和@Transactional注解有時候會失效的原因一樣)。

下面定義一個Service:

兩個異步執行的方法test03()和test02()用來模擬項目中可能出現的耗時的操作,然后test()方法調用這兩個耗時的方法:

 

定義Controller:

 

 

執行方法,返回結果:

 

方法執行結果明顯與我們的預期不符,方法的輸出順序表示了test02()和test03()兩個異步方法居然同步執行了,也就是說@Aysnc注解失效了!

失效的原因是因為我們是在test()方法中直接調用的test02()和test03()方法,相當於是this.test02()和this.test03()調用的,也就是說真正調用test02()和test03()方法的是TestService對象本身調用的,而@Async和@Transactional注解本質使用的是動態代理,真正應該是TestService的代理對象調用test02()和test03()方法。其實Spring容器在初始化的時候Spring容器會將含有AOP注解的類對象“替換”為代理對象(簡單這么理解),那么注解失效的原因就很明顯了,就是因為調用方法的是對象本身而不是代理對象,因為沒有經過Spring容器,那么解決方法也會沿着這個思路來解決。

網上有不少博客說解決方法就是將要異步執行的方法單獨抽取成一個類,這樣的確可以解決異步注解失效的問題,原理就是當你把執行異步的方法單獨抽取成一個類的時候,這個類肯定是被Spring管理的,其他Spring組件需要調用的時候肯定會注入進去,這時候實際上注入進去的就是代理類了,其實還有其他的解決方法,並不一定非要單獨抽取成一個類。

解決方式一:在TestService中通過上下文獲取自己的代理對象調用異步方法
其實我們的注入對象都是從Spring容器中給當前Spring組件進行成員變量的賦值,由於TestService使用了AOP注解,那么實際上TestService在Spring容器中實際存在的是它的代理對象。

工具類可以參考我的另一篇博客:https://blog.csdn.net/Dongguabai/article/details/80788646

 

 

解決方式二:開啟cglib代理,手動獲取Spring代理類

在啟動類上加上:

 

 

使用AopContext.currentProxy()獲取當前代理類:

這里為了證明Spring容器中的對象就是當前代理類對象特地輸出了一句話:

 

 

運行結果:

 

OK,問題完美解決!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM