Spring框架05-IoC循环依赖

Spring IoC 循环依赖问题

什么是循环依赖

循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean互相持有对⽅,最终造成闭环。⽐如A 依赖于B,B依赖于C,C⼜依赖于A
image.pngjava

注意,这⾥不是函数的循环调⽤,是对象的相互依赖关系。循环调⽤其实就是⼀个死循环,除⾮有终结条件spring

Spring中循环依赖场景有:ide

  • 构造器的循环依赖(构造器注⼊)
  • Field属性的循环依赖(set注⼊)
其中,构造器的循环依赖问题⽆法解决,只能拋出 BeanCurrentlyInCreationException异常,在解决属性循环依赖时,spring采⽤的是提早暴露对象的⽅法

循环依赖处理机制

  • 单例 bean 构造器参数循环依赖(⽆法解决)
  • prototype 原型 bean循环依赖(⽆法解决)
    对于原型bean的初始化过程当中不管是经过构造器参数循环依赖仍是经过set⽅法产⽣循环依赖,Spring都 会直接报错处理。

单例bean经过setXxx或者@Autowired进⾏循环依赖

image.png

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);

}

});
  • Spring容器初始化ClassA经过构造器初始化对象后提早暴露到Spring容器
  • ClassA调⽤setClassB⽅法,Spring⾸先尝试从容器中获取ClassB,此时ClassB不存在Spring容器中
  • Spring容器初始化ClassB,同时也会将ClassB提早暴露到Spring容器中
  • ClassB调⽤setClassA⽅法,Spring从容器中获取ClassA ,由于第⼀步中已经提早暴露了ClassA,所以能够获取到ClassA实例spa

    • ClassA经过spring容器获取到ClassB,完成了对象初始化操做
  • 这样ClassA和ClassB都完成了对象初始化操做,解决了循环依赖问题
相关文章
相关标签/搜索