循环依赖解释
bean A 属性注入时依赖bean B ,并且bean B属性注入时也依赖bean A ,造成 bean A 和bean B 都无法完成初始化问题,形成了闭环。
注意
项目中存在Bean的循环依赖,是Bean对象职责划分不明确、代码质量不高的表现,如果存在大量的Bean之间循环依赖,那么代码的整体设计也就越来越糟糕。所以SpringBoot在后续的版本中终于受不了这种滥用,默认把循环依赖给禁用了!从2.6版本开始,如果你的项目里还存在循环依赖,SpringBoot将拒绝启动!
spring 如何解决循环依赖的?
Spring解决循环依赖的核心思想在于提前曝光,使用三级缓存进行提前曝光。
使用三级缓存去解决的。三个Map
一级缓存 缓存的完整的bean 即 完成了实例化和属性注入的bean
二级缓存 缓存的是半成品的bean 即完成了实例化但未属性注入的bean
三级缓存 缓存的是bean工厂:
解决过程
开始实例化一个bean-> 属性中依赖bean,向一级缓存中获取,发现没有-> 再向二级缓存中获取,发现没有
-> 从三级缓存中获取bean工厂,通过getObject() 方法,获取对象,放到二级缓存->当前bean引用二级缓存中的bean->最后再对二级缓存中的bean进行属性装配。
SpringBoot2.6.0及以上 具体解决方案
建议不要这么做,循环依赖的出现表明代码质量太低
最简单的方法在yaml或properties中配置spring.main.allow-circular-references=true 支持循环依赖即可
示例
TestBService 实现类 TestBServiceImpl 中 注入 TestService对象
TestService 实现类 TestServiceImpl 中注入 TestBService对象
@Service
public class TestBServiceImpl extends ServiceImpl<TestBMapper, TestB>
implements TestBService {
@Autowired
private TestService testService;
}
@Service
public class TestServiceImpl extends ServiceImpl<TestAMapper, TestA>
implements TestService {
@Autowired
private TestBService testBservice;
}
在 application.yml 中
spring:
main:
## 支持循环依赖
allow-circular-references: true