循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean互相持有对⽅,最终造成闭环。⽐如A 依赖于B,B依赖于C,C⼜依赖于Ajava
注意,这⾥不是函数的循环调⽤,是对象的相互依赖关系。循环调⽤其实就是⼀个死循环,除⾮有终结条件spring
Spring中循环依赖场景有:ide
其中,构造器的循环依赖问题⽆法解决,只能拋出 BeanCurrentlyInCreationException异常,在解决属性循环依赖时,spring采⽤的是提早暴露对象的⽅法
set
⽅法产⽣循环依赖,Spring都 会直接报错处理。Spring的循环依赖的理论依据基于Java的引⽤传递,当得到对象的引⽤时,对象的属性是能够延后设置的,可是构造器必须是在获取引⽤以前函数
Spring经过setXxx或者@Autowired⽅法解决循环依赖实际上是经过提早暴露⼀个ObjectFactory对象来完成的,简单来讲ClassA在调⽤构造器完成对象初始化以后,在调⽤ClassA的setClassB⽅法以前就把ClassA实例化的对象经过ObjectFactory提早暴露到Spring容器中this
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } //将初始化后的对象提早已ObjectFactory对象注⼊到容器中addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd,bean); } });
ClassB调⽤setClassA⽅法,Spring从容器中获取ClassA ,由于第⼀步中已经提早暴露了ClassA,所以能够获取到ClassA实例spa