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