参考博客原文地址:

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循环依赖问题的更多相关文章

  1. Spring源码-IOC部分-Spring是如何解决Bean循环依赖的【6】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  2. 从源码解读Spring如何解决bean循环依赖

    1 什么是bean的循环依赖 循环依赖的原文是circular reference,指多个对象相互引用,形成一个闭环. 以两个对象的循环依赖为例: Spring中的循环依赖有 3 种情况: 构造器(c ...

  3. Springboot循环依赖实践纪实

    测试的Springboot版本: 2.6.4,禁止了循环依赖,但是可以通过application.yml开启(哈哈) @Lazy注解解决循环依赖 情况一:只有简单属性关系的循环依赖 涉及的Bean: ...

  4. spring3 循环依赖

    循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...

  5. Spring的循环依赖问题

    spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类: 在Spring中将循环依赖的处理分成了3种情况: 构造器循环依赖 ...

  6. DI 之 3.2 循环依赖 (伍)

    3.2.1  什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA, ...

  7. Spring源代码解析 ---- 循环依赖

    一.循环引用: 1. 定义: 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比方CircularityA引用CircularityB,CircularityB引用Circularit ...

  8. 开涛spring3(3.2) - DI之循环依赖

    3.2.1  什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用 CircleC,CircleC引用CircleA ...

  9. Spring循环依赖问题

    什么是循环依赖? 循环依赖就是循环引用,指两个或多个bean互相持有对方,比如说TestA引用TestB.TestB引用TestA,最终形成一个闭环. 注意:循环依赖不是指循环调用. 循环调用:指方法 ...

随机推荐

  1. 获取navigationController中的控制器

    @implementation UIViewController (UIViewControllerExt) - (void)popViewController:(NSString *)control ...

  2. 为什么在/etc/profile中设定的环境变量,对子进程可见

    系统启动时有个过程是启动初始shell,执行一些固定目录下的脚本,比如/etc/profile.....(系统启动时执行一次),我们在这些文件中添加并导出环境变量 这样shell启动的其它的进程就具备 ...

  3. jmeter分布式linux负载机,windows主控机

    1.将参数化文件上传到linux服务器,放在linux上jmeter的bin路径下 2.设置server.rmi.ssl.disable=true 分别修改主控机和负载机的jmeter.propert ...

  4. 学习进度-16 python爬虫

    爬虫是一个程序,这个程序的目的就是为了抓取万维网信息资源,比如你日常使用的谷歌等搜索引擎,搜索结果就全都依赖爬虫来定时获取 从百度可以看出来 爬虫与python关系很紧密, 爬虫的目标对象也很丰富,不 ...

  5. Linux CentOS7 VMware find命令、文件名后缀

    一.find命令 Linux系统中的 find 命令在查找文件时非常有用而且方便.它可以根据不同的条件来查找文件,例如权限.拥有者.修改日期/时间.文件大小等等.在这篇文章中,我们将学习如何使用 fi ...

  6. 解决dotnet-Angular的跨域(cors)问题

    解决dotnet-Angular的跨域(cors)问题 前言 之前学了点 Angular ,打算用 dotnet core 做后端,之前没接触过这方面的东西,理所当然的遇到了跨域问题,之后也解决了,所 ...

  7. 通过JAVA反射修改JDK1.6*当中DNS缓存内容

    时间 2012-05-28 17:09:03  Taobao QA Team原文  http://qa.taobao.com/?p=15523 为了实现性能压测时的域名动态绑定功能,尝试通过java反 ...

  8. 开源Web测试工具介绍

    HtmlUnitHtmlUnit 是 JUnit 的扩展测试框架之一.HtmlUnit 将返回文档模拟成 HTML,这样您便可以直接处理这些文档了.HtmlUnit 使用例如 table.form 等 ...

  9. Linux ---- 查看当前TCP连接数

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数netstat -nat|grep -i "80"|wc -l 2)统计httpd协议 ...

  10. MIT课程

    8.02  Physics II (电磁学基础) Introduction to electromagnetism and electrostatics: electric charge, Coulo ...