问题出现
编写了两个类来测试一下循环依赖:
testa类
@component
public class testa {
@autowired
private testb testb;
public void afunc() {
system.out.println("testa");
}
}
testb类
@component
public class testb {
@autowired
private testa a;
public void bfunc() {
system.out.println("testb");
}
}
没想到启动报错了
description: the dependencies of some of the beans in the application context form a cycle: ┌─────┐ | testa (field private com.example.springtest.testb com.example.springtest.testa.testb) ↑ ↓ | testb (field private com.example.springtest.testa com.example.springtest.testb.a) └─────┘ action: relying upon circular references is discouraged and they are prohibited by default. update your application to remove the dependency cycle between beans. as a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true
可是印象里,spring不是默认支持循环依赖的吗?哎?
问题溯源
首先按照之前对spring循环依赖的理解,我们知道spring有三级缓存来解决循环依赖的问题,假设先创建的是testa,那么存在以下的推导:
docreatebean(testa) -> populatebean(testa) -> docreatebean(testb) -> populatebean(testb) -> testb添加到ioc容器中 -> testa添加的ioc容器中
那为啥还是出现了循环依赖问题呢?
根据报错提示我们可以设置spring.main.allow-circular-references为true来解决循环依赖问题,这个配置在spring中不说默认为true吗,难道是springboot对这个配置进行了修改?
在docreatebean中有一段关键的代码
// eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like beanfactoryaware.
boolean earlysingletonexposure = (mbd.issingleton() && this.allowcircularreferences &&
issingletoncurrentlyincreation(beanname));
if (earlysingletonexposure) {
if (logger.istraceenabled()) {
logger.trace("eagerly caching bean '" + beanname +
"' to allow for resolving potential circular references");
}
addsingletonfactory(beanname, () -> getearlybeanreference(beanname, mbd, bean));
}
通过断点调试可以看到this.allowcircularreferences的值为false

earlysingletonexposure为false,那三级缓存中就没有testa,在populatebean(testb)中又会走getsingleton(),最终在beforesingletoncreation抛出了循环依赖的异常。
/** cache of singleton factories: bean name to objectfactory. */ private final map<string, objectfactory<?>> singletonfactories = new hashmap<>(16);
至于this.allowcircularreferences的值为什么默认是false,我的springboot的版本使用的是2.7.x,然后

2.6版本默认不支持循环依赖了
解决方法
在application.properties中,设置spring.main.allow-circular-references=true
![]()
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论