Springboot Bean循环依赖问题
参考博客原文地址:
https://www.jb51.net/article/168398.htm
https://www.cnblogs.com/mianteno/p/10692633.html
http://www.pianshen.com/article/4112200143/

1.构造器依赖循环
代码示例:
@Component
public class A {
private B b;
@Autowired
public A(B b) {
this.b=b;
}
}
@Component
public class B {
private C c;
@Autowired
public B(C c) {
this.c = c;
}
}
@Component
public class C {
private A a;
@Autowired
public C(A a) {
this.a=a;
}
}
启动运行后运行结果:

可以看到异常的信息:
//org.springframework.beans.factory.BeanCurrentlyInCreationException
public BeanCurrentlyInCreationException(String beanName) {
super(beanName,
"Requested bean is currently in creation: Is there an unresolvable circular reference?");
}
这种循环依赖没有什么解决办法,因为JVM虚拟机在对类进行实例化的时候,需先实例化构造器的参数,而由于循环引用这个参数无法提前实例化,故只能抛出错误。
2.属性注入依赖循环
代码示例:
@Component
public class A {
@Autowired
private B b;
public A() {
System.err.println(b);
}
}
@Component
public class B {
@Autowired
private C c;
public B() {
System.err.println(c);
}
}
@Component
public class C {
@Autowired
private A a;
public C() {
System.err.println(a);
}
}
启动运行后运行结果:
//程序正常启动,输出如下
null
null
null
结论:
Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题
3.源码分析 构造器循环依赖异常步骤及原因:
创建一个Bean的过程是:实例化->初始化(属性)->放到缓存中,如下图

这张图是核心

getSingleton源码:

//首次创建的beanName放入singletonsCurrentlyInCreation中
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
构造器循环依赖,在初始化C时,需要先实例化A,但是A已经在singletonsCurrentlyInCreation有预实例化的记录了,所以此处抛出异常。
public BeanCurrentlyInCreationException(String beanName) {
super(beanName,
"Requested bean is currently in creation: Is there an unresolvable circular reference?");
}
源码分析 Spring如何解决属性注入 依赖循环问题:
//相关类
org.springframework.beans.factory.support.DefaultListableBeanFactory
org.springframework.beans.factory.support.AbstractBeanFactory
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory





可以看到,在实例化后,Bean被添加到singletonFactories中了,所以可以获取到Bean实例,解决了属性循环依赖问题
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
4.最终总结:
构造器循环依赖:没有什么解决办法,因为JVM虚拟机在对类进行实例化的时候,需先实例化构造器的参数,而由于循环引用这个参数无法提前实例化,故只能抛出错误。
属性循环依赖:Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题
Springboot Bean循环依赖问题的更多相关文章
- Spring源码-IOC部分-Spring是如何解决Bean循环依赖的【6】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- 从源码解读Spring如何解决bean循环依赖
1 什么是bean的循环依赖 循环依赖的原文是circular reference,指多个对象相互引用,形成一个闭环. 以两个对象的循环依赖为例: Spring中的循环依赖有 3 种情况: 构造器(c ...
- Springboot循环依赖实践纪实
测试的Springboot版本: 2.6.4,禁止了循环依赖,但是可以通过application.yml开启(哈哈) @Lazy注解解决循环依赖 情况一:只有简单属性关系的循环依赖 涉及的Bean: ...
- spring3 循环依赖
循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...
- Spring的循环依赖问题
spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类: 在Spring中将循环依赖的处理分成了3种情况: 构造器循环依赖 ...
- DI 之 3.2 循环依赖 (伍)
3.2.1 什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA, ...
- Spring源代码解析 ---- 循环依赖
一.循环引用: 1. 定义: 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比方CircularityA引用CircularityB,CircularityB引用Circularit ...
- 开涛spring3(3.2) - DI之循环依赖
3.2.1 什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用 CircleC,CircleC引用CircleA ...
- Spring循环依赖问题
什么是循环依赖? 循环依赖就是循环引用,指两个或多个bean互相持有对方,比如说TestA引用TestB.TestB引用TestA,最终形成一个闭环. 注意:循环依赖不是指循环调用. 循环调用:指方法 ...
随机推荐
- Python 基础之字符串操作,函数及格式化format
一.字符串的相关操作 1.字符串的拼接 + strvar1 = "我爱你,"strvar2 = "亲爱的姑凉"res = strvar1 + strvar2pr ...
- 十七 Spring的JDBC模版:使用开源连接池,DBCP,C3P0
DBCP的配置以及使用 引入jar包
- 五子棋C#源码,网络对战版---转载--待学习
五子棋C#源码,网络对战版 支持网络对战的C#五子棋源码下载,VS2010环境编译后可运行,需要先输入ip地址才行,不是单机版的.部分代码摘录如下://将接收的消息转换成自定义集合MessClass ...
- PAT B1019/A1069 数字黑洞
给定任一个各位数字不完全相同的四位正整数,如果先把四个数字按照非递增排序,再按照非递减排序,然后用第一个数字减第二个数字,将得到一个新的数字,一直重复这样做,很快就会停在有“数字黑洞”之称的6147, ...
- ch13 事件(思维导图)
- SpringBoot初试牛刀
新建 Spring Boot 项目常用的两种方式 你可以通过 https://start.spring.io/ 这个网站来生成一个 Spring Boot 的项目. 你可以选择自己喜欢的依赖进行加载到 ...
- 几种编辑器的markdown-toc生成目录在github上的表现
Vscode vscode的markdown-toc插件的实现是比较好的, 目前发现的问题就只有在自动生成带链接目录的时候无法正确识别和生成一些特殊的字符. 例如: ▶ 这导致在标题中不能加入特殊字符 ...
- HTML设置目标页面在新窗口打开
在使用<a></a>标签进行超链接跳转时,目标页面默认在当前页面中打开. 如果希望当前页面中所有超链接跳转页面的时候,都在新窗口中打开,那么只需要在head标签中设置 base ...
- DevOps - 总结
章节 DevOps – 为什么 DevOps – 与传统方式区别 DevOps – 优势 DevOps – 不适用 DevOps – 生命周期 DevOps – 与敏捷方法区别 DevOps – 实施 ...
- [noip2014]P2312 解方程
P2312 解方程 其实这道题就是求一个1元n次方程在区间[1, m]上的整数解. 我们枚举[1, m]上的所有整数,带进多项式中看看结果是不是0即可. 这里有一个技巧就是秦九韶算法,请读者自行查看学 ...