Spring Bean 循环依赖源码解析

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean()处,生成bean的核心方法是createBean(beanName, mbd, args);

// scope是单例--> 创建一个bean的实例对象
if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, () -> {
      try {
         // 本质是构造器的createInstance()方法创建了对象
         return createBean(beanName, mbd, args);
      } catch (BeansException ex) {
         //从单例缓存中移除实例
         //创建过程中,允许循环引用解析。
         //同时删除所有接收到临时引用的bean。
         destroySingleton(beanName);
         throw ex;
      }
   });
  • 创建bean的时候,会去调用一遍org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#Singleton()方法
/**
 * 获取单例bean对象
 * singletonObjects --> 一级缓存,单例池,也就是通常所说的Spring容器,所有单例的bean都是从中获取对象
 * earlySingletonObjects --> 二级缓存,避免一个bean被多个bean依赖,而出现多次调用工厂的情况
 * singletonFactories --> 三级缓存,工厂代理,其中包含了生成bean的过程。
 * <p>
 * 循环依赖过程:
 * A <--> B 互相依赖
 * ① 创建bean A,创建过程中(标记A正在创建),填充A的属性,发现需要bean B
 * ② 创建bean B,创建过程中(标记B正在创建),填充B的属性,发现需要bean A
 * ③ 再次通过 getSingleton() 方法去创建A
 * ④ 一级缓存(单例池)存在A,则返回,否则走第⑤步
 * ⑤ 发现A正在创建中,查看二级缓存,存在||不循序循环依赖则返回,存在&&允许循环依赖则走第⑥步
 * ⑥ 三级缓存(生产工厂)获取bean A
 * ⑦ 填充bean B-->放入一级缓存
 * ⑧ 填充bean A-->放入一级缓存
 *
 * @param beanName            默认为小写类名
 * @param allowEarlyReference 是否允许循环依赖
 * @return
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   //  通过beanName去一级缓存(单例池)中获取对象
   Object singletonObject = this.singletonObjects.get(beanName);
   //  对象为空 && beanName的这个bean正在创建过程中--
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      //  通过beanName去二级缓存中获取对象
      singletonObject = this.earlySingletonObjects.get(beanName);
      //  二级缓存不存在对象且 该beanName所对应的beanDefinetion中的allowEarlyReference (支持循环依赖)为true
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // 单例模式-锁双重判断
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               // 二级缓存再去获取一次对象
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  // 最终去三级缓存,工厂中去生成对象
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     singletonObject = singletonFactory.getObject();
                     // 放入二级缓存
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     // 三级缓存移除
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值