Spring循环依赖

Spring循环依赖

什么是循环依赖

​ 两个或两个以上的bean,互相持有,形成闭环。例如:A依赖B,B依赖C,C依赖A;形成相互依赖。

Spring中循环依赖
  • 构造方法中的循环依赖。

    @Component
    public class TestA {
    
        private TestB testB;
    
        TestA (TestB testB) {
            this.testB = testB;
        }
    }
    
    @Component
    public class TestB {
    
        private TestA testA;
    
        TestB(TestA testA) {
            this.testA = testA;
        }
    }
    
    Description:
    
    The dependencies of some of the beans in the application context form a cycle:
    
    ┌─────┐
    |  testA defined in file [H:\strive\target\classes\com\spring\circleDepend\TestA.class]
    ↑     ↓
    |  testB defined in file [H:\strive\target\classes\com\spring\circleDepend\TestB.class]
    └─────┘
    
    

    可以看到spring是不能解决这种构造方法的循环依赖问题。因为创建当前对象的时候,需要调用当前对象的构造方法,由于带参的构造方法,总是互相持有,所以不能创建成功。

  • setter中的循环依赖。循环依赖只是在属性中,不在构造方法中。

    @Component
    public class TestA {
        @Autowired
        private TestB testB;
    }
    
    @Component
    public class TestB {
        @Autowired
        private TestA testA;
    }
    

    这种境况是可以成功创建对象的。

Spring是如何解决循环依赖的

​ Spring默认一级缓存是存放所有已完成初始化的bean的。

  • 二级缓存

​ 看一下Spring创建bean的简易过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8kMkXeQe-1614318458012)(C:\Users\whrdd-pc107\AppData\Roaming\Typora\typora-user-images\image-20210226104702686.png)]

​ 所以我们只需要在创建bean实例的时候,提前把bean加入到缓存,让bean尽早的暴露,循环依赖在获取bean的进行属性填充的时候,可以先在缓存中直接拿到bean的引用进行属性填充。
在这里插入图片描述

​ 二级缓存的问题:如果此时TestA创建完成之后,又需要生成TestA的代理类ProxyTestA,但是此时TestB中testA的属性还是原有的TestA的引用,而不是代理类ProxyTestA,就会导致TestB中属性不是一个对象。

  • 三级缓存

    三级缓存,多了一级缓存来存放生成bean的工厂。
    在这里插入图片描述

Spring源码解析

第一级缓存(也叫单例池):Map<String, Object> singletonObjects,存放已经经历了完整生命周期的 Bean 对象

第二级缓存:Map<String, Object> earlySingletonObjects,存放早期暴露出来的 Bean 对象,Bean 的生命周期未结束(属性还未填充完),可能是代理对象,也可能是原始对象

第三级缓存:Map<String, ObjectFactory<?>> singletonFactories,存放可以生成 Bean 的工厂,工厂主要用来生成 Bean 的代理对象

// Eagerly cache singletons to be able to resolve circular references 主动缓存单例,以便能够解析循环引用
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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");}
   // lamnada lazy加载 
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 如果bean的后置处理PostProcessors有的话,需要执行所有的后置处理,来得到一个期望的bean,生成一个代理类
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
   return exposedObject;
}
// 如果一级缓存中不包含这个bean,就加入到三级缓存中(加入的是创建bean的工厂),并把二级缓存中移除
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   synchronized (this.singletonObjects) {
      if (!this.singletonObjects.containsKey(beanName)) {
         this.singletonFactories.put(beanName, singletonFactory);
         this.earlySingletonObjects.remove(beanName);
         this.registeredSingletons.add(beanName);
      }
   }
}
// 获取这个bean的单例的时候
// 如果一级缓存中没有,就从二级缓存中获取,二级缓存中没有就去三级缓存中获取
// 从三级缓存中获取创建bean的factory,从factory拿到bean,移除三级缓存中的bean,加入到二级缓存。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return singletonObject;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值