SpringbootBean循环依赖问题
参考博客原⽂地址:
1.构造器依赖循环代码⽰例:@Componentpublic class A { private B b; @Autowired public A(B b) { this.b=b; }}
@Componentpublic class B { private C c; @Autowired public B(C c) { this.c = c; }}
@Componentpublic class C { private A a; @Autowired public C(A a) { this.a=a; }}
启动运⾏后运⾏结果:
可以看到异常的信息:
//org.springframework.beans.factory.BeanCurrentlyInCreationExceptionpublic BeanCurrentlyInCreationException(String beanName) { super(beanName,
\"Requested bean is currently in creation: Is there an unresolvable circular reference?\"); }
这种循环依赖没有什么解决办法,因为JVM虚拟机在对类进⾏实例化的时候,需先实例化构造器的参数,⽽由于循环引⽤这个参数⽆法提前实例化,故只能抛出错误。
2.属性注⼊依赖循环代码⽰例:
@Componentpublic class A { @Autowired private B b; public A() {
System.err.println(b); }}
@Componentpublic class B { @Autowired private C c; public B() {
System.err.println(c); }}
@Componentpublic class C { @Autowired private A a; public C() {
System.err.println(a); }}
启动运⾏后运⾏结果://程序正常启动,输出如下nullnullnull
结论:
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.DefaultListableBeanFactoryorg.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,解决了循环依赖的问题