您好,登錄后才能下訂單哦!
小編給大家分享一下SpringBoot使用Async注解失效怎么辦,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
在Java應用中,絕大多數情況下都是通過同步的方式來實現交互處理的;但是在處理與第三方系統交互的時候,容易造成響應遲緩的情況,之前大部分都是使用多線程來完成此類任務,其實,在spring 3.x之后,就已經內置了@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容器中實際存在的是它的代理對象。
執行結果,異步方法異步執行了:
開啟cglib代理,手動獲取Spring代理類
在啟動類上加上:
使用AopContext.currentProxy()獲取當前代理類:
這里為了證明Spring容器中的對象就是當前代理類對象特地輸出了一句話:
運行結果:
OK,問題完美解決!
application.properties配置如下:
#java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available. # 增加@EnableAspectJAutoProxy spring.aop.auto=true #開啟CGLIB代理 spring.aop.proxy-target-class=true
1、當前類中其他函數調用有 @Async 注解的函數
2、當前類中有多態,方法名相同
3、啟動類未加@EnableAsync
以上是“SpringBoot使用Async注解失效怎么辦”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。