参考博客原文地址:

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,解决了循环依赖的问题

最新文章

  1. 图的割点 | | jzoj【P1230】 | | gdoi | |备用交换机
  2. C语言打乱一组数字顺序
  3. 实战 SQL Server 2008 数据库误删除数据的恢复
  4. SQL创建linkserver
  5. struct和typedef struct在c++中的用法
  6. Hive中数据的导入与导出
  7. 【CF850E】Random Elections(FWT)
  8. 网络编程基础【day10】:我是一个线程(四)
  9. Pycharm自动添加文件头
  10. [Luogu 3401] 洛谷树
  11. 转载:详解Java 自动装箱与拆箱的实现原理
  12. C++ 常用算法
  13. Java Web(五) 监听器Listener
  14. org注释包
  15. 注解Annotation实现原理与自定义注解例子
  16. Java基础87 MySQL数据约束
  17. log4j(五)——如何控制不同目的地的日志输出?
  18. [備註] 安裝與整合 xUnit 測試框架@VS2012
  19. 关于Cocos2d-x中使用完Blink动作后精灵突然消失的问题的解决
  20. HDU 3436 Queue-jumpers

热门文章

  1. Hive的存储和MapReduce处理——数据清洗(Part2)
  2. NSNotFound
  3. 获取navigationController中的控制器
  4. Memcached 最新版本发布,不再仅仅是个内存缓存了
  5. easyui学习索引页
  6. Mac OS 下升级gcc遇到的坑
  7. js网页拉起支付宝支付
  8. Day1-E-BZOJ1293
  9. javaweb框架--自定义标签与freemaker结合
  10. intel关于spark gc的优化建议