问题描述
spring明明使用三级缓存解决循环依赖,那为什么业务代码两个service间使用autowire注解互相依赖,还会因循环依赖问题而报错?
演示


启动spring容器时,就会因循环依赖问题而启动失败
问题分析:
spring明明是使用三级缓存解决了循环依赖问题,除了这两种情况无法解决外:①使用构造函数注入对象;②bean的作用域是原型(prototype)
那已经避开这两种情况,使用@Autowire相互依赖,仍然会报依赖循环问题?
spring是如何使用三级缓存解决循环依赖问题的?
对象的创建过程:
①实例化(createBeanInstance);②属性注入(populateBean);③初始化过程(initializeBean)。
循环依赖时发生在属性注入阶段;
而spring是这样解决的:
1、先实例化userService,并对该bean创建对象工厂factoryBean,并将其getObjct逻辑作为lambda表达式放入第三级缓存(singletonFactories);
2、userService要注入orderService,就先从第一级缓存找orderService,找不到就判断是否在创建中,此时就开始创建orderService,也是步骤1的操作,此时orderService要注入userService,判断它在创建中,就到二级缓存中找 ,找不到就到三级缓存中找;
3、因为步骤1,所以可以从三级缓存中找到,就执行getObject逻辑生成userService对象(此时仍然未初始化完毕),或判断有transactional注解或自定义aop,就会生成userService的代理对象,并放入二级缓存中,并删除三级缓存,然后orderService还要完成接下来的初始化阶段,此时orderService已经创建完毕,可以放入一级缓存;
4、因步骤3,userService也可以注入orderService,再完成初始化即可;
spring就是这样完美的解决了依赖循环;
找到问题原因
于是翻看源码发现,在执行BeanFactoryPostProcessor的阶段是可以关闭循环依赖的开关,于是就思考是不是spring默认关闭了循环依赖的开关
果然,查看官网发现

在2.6.0版本后,就默认关闭循环依赖的开关。
解决问题
开启循环依赖开关

思考关闭循环依赖开关的原因
其实循环依赖说到底是因为编写代码不规范导致的,为了约束代码规范,于是spring官方默认关闭了开关,但仍然保留开启循环依赖;
3151

被折叠的 条评论
为什么被折叠?



