@Async让我流泪 置顶!

2020-06-17

背景

2020-06-17,接到一个导出数据的任务 ,看了下用sql做不了(能力不够),于是准备写段代码去跑.

过程

于是就写啊写啊写啊写.因为需要先导入一个Excel数据作为查询条件(2W多),而且需要关联一个HIS系统查询一些数据(很笨重,查询很慢),查询了很久很久都不会写回结果 ,所以直接准备异步处理.调用后前端直接返回成功 ,后台异步查数据,写Excel到服务器,到时候直接去服务器下载Excel.

启动

写了半天,终于写好了,准备先行测试一下,结果他NND启动不了,报循环依赖的错误
!
image.png
别说话 ,对,当时我就懵逼了.我也没在这个类中新注入其他的接口或者实现类,为什么以前没问题现在就出现问题了.不瞒大家,我蒙蔽了10分钟.于是,百度.

原因

百度了半天,发现是因为我为了不让前端等待添加的**@Async注解**坏事儿了 .
Spring是解决了属性的循环依赖的(还有个是构造器的循环依赖,解决不了),在实例化一个类的时候,会将注入进来的Bean一同实现,放入缓存 .当实例到这个类的时候会先检查缓存中有不有这个实例,有的话直接使用,没有在实例化(能力有限,说的比较简陋).
所以类中循环调用,一般不会有大问题

但是! 当循环依赖的类中使用了 @Async注解后情况有所不同.
简单的讲就是在启动程序的时候,Spring已经对A里的B、C加载完成,当准备创建B类的时候发现使用了@Async注解,即spring又需将该Bean代理一次,然后Spring发现该Bean已经被其他对象注入,这里就是问题的关键所在了。

解决

最后我屈服了,去掉了异步注解.在方法中开启了一个线程去处理.

最后

更多请参考 :@Async注解使用不当引发的spring循环依赖思考