@Async注解导致循环依赖,BeanCurrentlyInCreationException异常
使用@Async異步注解導致該Bean在循環依賴時啟動報BeanCurrentlyInCreationException異常的根本原因分析,以及提供解決方案
?
今天在自己項目中使用@Async的時候,碰到了一個問題:Spring循環依賴(circular reference)問題。
或許剛說到這,有的小伙伴就會大驚失色了。Spring不是解決了循環依賴問題嗎,它是支持循環依賴的呀?怎么會呢?
出現使用@Async導致循環依賴問題的必要條件:
為什么有小伙伴跟我說:我使用@Async即使本類方法調用也從來木有遇到這個錯誤啊?難道它不常見?
為此經過我的一番調查,包括看一些同事、小伙伴的代碼發現:并不是使用@Async沒有啟動報錯,而是他本類調用的時候直接調用的方法,這樣@Async是不生效的但小伙伴卻全然不知而已。
至于@Async沒生效這種問題為何沒報出來???甚至過了很久很久都沒人發現和關注??
其實道理很簡單,它和事務不生效不一樣,@Async若沒生效99%情況下都不會影響到業務的正常進行,因為它不會影響數據正確性,只會影響到性能(無非就是異步變同步唄,這是兼容的)
我們知道事務不生效和@Async不生效的根本原因都是同一個:直接調用了本類方法而非接口方法/代理對象方法。
解決這類不生效問題的方案一般我們都有兩種:
自己注入自己,然后再調用接口方法(當然此處的一個變種是使用編程方式形如:AInterface a = applicationContext.getBean(AInterface.class);這樣子手動獲取也是可行的~~~本文不討論這種比較直接簡單的方式)
使用AopContext.currentProxy();
讓不調用本類的@Async方法不就可以了;讓不產生循環依賴不就可以了,這也是解決方案
1:新建一個線程池配置類AsyncConfig
@EnableAsync @Configuration public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10); //核心線程數executor.setMaxPoolSize(20); //最大線程數executor.setQueueCapacity(1000); //隊列大小executor.setKeepAliveSeconds(300); //線程最大空閑時間executor.setThreadNamePrefix("fsx-Executor-"); //指定用于新創建的線程名稱的前綴。executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒絕策略(一共四種,此處省略)executor.initialize();return executor;}// 異常處理器:當然你也可以自定義的,這里我就這么簡單寫了~~~@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return new SimpleAsyncUncaughtExceptionHandler();} }?
?
2:新增一個HelloService接口
public interface HelloService {Object hello(Integer id);void fun1(); }?
3:新增一個HelloServiceImpl實現類
@Service public class HelloServiceImpl implements HelloService{@Autowiredprivate HelloService helloService;@Overridepublic Object hello(Integer id) {System.out.println("線程名稱:" + Thread.currentThread().getName());helloService.fun1(); // 使用接口方式調用,而不是thisreturn "service hello";}@Async@Overridepublic void fun1() {System.out.println("線程名稱:" + Thread.currentThread().getName());} }?
4:新增一個異步測試類
@SpringBootTest public class AsyncTest {@Autowiredprivate HelloService helloService;@Testpublic void test(){helloService.hello(1);} }?
5:啟動測試類
此種做法首先是Spring中一個典型的循環依賴場景:自己依賴自己。本以為能夠像解決事務不生效問題一樣依舊屢試不爽,但沒想到非常的不給面子,啟動即報錯
報錯如下BeanCurrentlyInCreationException異常
?
?
6:解決方法
在HelloServiceImpl類上@Autowired注解下加上@Lazy注解,即懶加載
?
7:啟動項目
輸出如下,成功了
?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的@Async注解导致循环依赖,BeanCurrentlyInCreationException异常的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用cookies跳过登陆验证码
- 下一篇: MFC版链表实现稀疏多项式相加减