参考文章-支持注入循环依赖:https://blog.csdn.net/u010853261/article/details/77940767

 https://blog.csdn.net/fedorafrog/article/details/104550165

一、背景

清分服务添加一个异步处理功能(@asyc),本地测试时发现启动服务后有时正常有时异常。

 

问题出现场景详细描述(都是autowird注入,构造器是不可能支持循环依赖的,上面链接有详细描述)

ServiceA->ServiceB ,ServiceB->ServiceA   serviceA中有@Async注解的方法启动并不会报错。

ServiceA->ServiceB ,ServiceB->ServiceA ,ServiceC->ServiceA  serviceA中有@Async注解的方法启动问题就来了。

 

说明:

1、bean的实例化过程:create bean →  cache bean → inject element → inject element → inject element ... ... → finish(debug模式可以跟踪完整的bean实例化过程)

2、非循环依赖场景

条件:A依赖B,如果先create A

实例化过程为:create A → cache A → create B → cache B → finish B → inject B to A → finish A。(被依赖对象先finish,即B先于A实例化完成)

3、循环依赖场景

条件:A依赖B,B依赖A,如果先create A

实例化过程为:create A → cache A → create B → cache B → inject A to B → finish B → inject B to A → finish A。(spring允许eagerly cached instance注入到其他bean中,eagerly cached instance 指已缓存但未finish的bean)

 

清分工程中bean的依赖比较复杂,抽象出下面的场景做说明:(下面的bean都为单例模式,非单例模式下bean不会进行cache,不支持循环依赖)

步骤1:A依赖B、C依赖B,B依赖C,并且B实现类的方法上存在@async注解,即B在实例化完成前会生成代理。
步骤2:A开始create,发现B未实例化,于是先cache A。
步骤3:B开始create,发现C未实例化,于是先cache B。
步骤4:C开始create,发现B已实例化,取出cache的B,注入C中,C finish。
(为什么B未实例化完就注入到C中了?that is not fully initialized yet - a consequence of a circular reference,因为存在循环依赖,所以允许先注入。猜测未做是否被代理的检测)
步骤5:生成B的代理类B@108e。
步骤6:B@108e注入到A时,发现B@108e的原始实例B已注入到循环引用的C中,却没有使用B的最终代理类B@108e,所以抛异常。

正常情况应该为B先finish,A和C后finish,这样可以保证B的最终代理类注入到A和C中。

 

小心陷阱

1、depends-on设置:如果A depends-on B,只会保证B先于A开始实例化(Creating instance of bean),但不保证B先于A实例完成(Finished creating instance of bean)。对于简单的bean,实例化完成顺序正常。

2、尽量保持bean的依赖关系简单。

3、保证bean加载顺序固定。

4、service注入的时候尽量注入mapper,否则经过多次迭代业务更改,循环依赖就容易暴露出来。

5、最简单有效的方法,加上@Lazy注解就ok,但是不保证日后业务拓展循环依赖循环懒加载会出现什么情况。

6、每次单独写个service,只提供这个注解方法,供某个service调用,全部聚合起来。

service--->            ------>service(异步)

    }  ----->service-----.>{

service--->            --------service(异步)
————————————————
版权声明:本文为CSDN博主「白底黑字」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lianhuazy167/article/details/66967673

posted on 2019-09-26 23:24  yoshion  阅读(476)  评论(0编辑  收藏  举报