Springboot Bean循环依赖问题
2024-09-02 10:53:02
参考博客原文地址:
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,解决了循环依赖的问题
最新文章
- 图的割点 | | jzoj【P1230】 | | gdoi | |备用交换机
- C语言打乱一组数字顺序
- 实战 SQL Server 2008 数据库误删除数据的恢复
- SQL创建linkserver
- struct和typedef struct在c++中的用法
- Hive中数据的导入与导出
- 【CF850E】Random Elections(FWT)
- 网络编程基础【day10】:我是一个线程(四)
- Pycharm自动添加文件头
- [Luogu 3401] 洛谷树
- 转载:详解Java 自动装箱与拆箱的实现原理
- C++ 常用算法
- Java Web(五) 监听器Listener
- org注释包
- 注解Annotation实现原理与自定义注解例子
- Java基础87 MySQL数据约束
- log4j(五)——如何控制不同目的地的日志输出?
- [備註] 安裝與整合 xUnit 測試框架@VS2012
- 关于Cocos2d-x中使用完Blink动作后精灵突然消失的问题的解决
- HDU 3436 Queue-jumpers