官网说明
官网循环依赖
官网意思是说,循环依赖出现的场景是构造器注入。
例如:类A通过构造函数注入需要类B的实例,类B通过构造函数注入需要类A的实例。如果为类A和类B配置bean以相互注入,Spring IoC容器将在运行时检测此循环引用,并抛出BeanCurrentlyIncrementationException。
bean a和bean B之间的循环依赖迫使一个bean在完全初始化之前注入另一个bean(典型的鸡和蛋场景)。
下面会详细从代码层面讲解怎么Spring人怎么检测处循环依赖的异常。
A,类B两个类相互依赖图如下:
代码如下
@ComponentpublicclassB{privateAa;publicB(Aa){this.a=a;}}
@ComponentpublicclassA{privateBb;publicA(Bb){this.b=b;}}
创建一个启动类ComponentBootStrap
@Configuration@ComponentScanpublicclassComponentBootStrap{publicstaticvoidmain(String[]args){AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(ComponentBootStrap.class);}}
启动,nice,正常报错。
分析异常
从getBean("beanName")的开始
首先将beanName放入一个集合中,如果集合中存在beanName,则抛出BeanCurrentlyInCreationException(beanName)
继续初始化bean
1 如果该bean依赖(这里指构造器注入)另一个bean s ,那么回到getBean("s")
3.2 完成bean的初始化
从集合中删除beanName
所以类A,B的分析如下:
创建bean之前放入集合中。
代码如下:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#beforeSingletonCreation
protectedvoidbeforeSingletonCreation(StringbeanName){if(!this.inCreationCheckExclusions.contains(beanName)&&!this.singletonsCurrentlyInCreation.add(beanName)){thrownewBeanCurrentlyInCreationException(beanName);}}
publicBeanCurrentlyInCreationException(StringbeanName){super(beanName,"Requestedbeaniscurrentlyincreation:Isthereanunresolvablecircularreference?");}
如何解决
官网也说过,改成setter注入即可。原理的话,下期再讲。