Spring 源码剖析 之 getBean

568 阅读11分钟

前言

个人认为Spring最大的魅力就是 依赖注入,从这篇文章开始我们再次对Spring的 IOC 部分进行一些梳理和复习。首先我们先讲一下 BeanFactorygetBean(String)。本文篇幅可能略长,请胖友们见谅


1 战略上俯视 getBean

1.1 getBean 的声明和实现

getBean

  • 方法声明于 org.springframework.beans.factory.BeanFactory,
  • 实现于org.springframework.beans.factory.support.AbstractBeanFactory

其实关于 BeanFactory 以及他的实现类有蛮多要讲的,我们后面有时间再细说

1.2 源码镇楼

1.2.1 getBean

/**
 * 空壳方法,具体的操作其实在 doGetBean
 * @param name the name of the bean to retrieve
 * @return
 * @throws BeansException
 */
@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}
  • getBean其实就是一个空壳方法,具体的实现都在doGetBean 这个方法里(熟悉 Spring 胖友们可能对这种写法已经习惯了)

1.2.2 doGetBean


/**
 * 获取bean
 *
 * @param name          bean的name
 * @param requiredType  获取的bean的类型,默认是null
 * @param args          实例化参数,默认是null
 * @param typeCheckOnly
 * @param <T>
 * @return
 * @throws BeansException 抛出异常
 */
protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {
   /**
    * <1> 获取beanName
    * 这一步操作主要是有2个原因
    * 1. 别名,Spring是支持bean别名的,我们要向获取真正的bean,必须要拿到最原始的beanName
    * 2. 工厂方法  当name以 & 字符开头时说明调用者想获取 FactoryBean本身,而不是FactoryBean所实现的类,
    *    但是BeanFactory中 普通bean和 FactoryBean本身的存储方式都是一致的,所以需要将 & 符号移除
    */
   String beanName = transformedBeanName(name);
   Object beanInstance;

   /**
    * 从缓存中获取单例 bean。
    * Spring 是使用 Map 作为 beanName 和 bean 单例bean实例的缓存的(其中key-> beanName, value -> bean)Map本身就不允许key重复
    * 所以这里暂时可以把 getSingleton(beanName) 等价于 beanMap.get(beanName)。当然实际原理并没有这么简单哈
    */
   Object sharedInstance = getSingleton(beanName);
   /**
    * 如果 sharedInstance == null,说明还没初始化好(BeanFactory并不会一开始就初始化好所有的bean,而是等到需要的时候才初始化--懒加载)
    * 如果 sharedInstance !=null 那 args 也没啥用了,因为不会再初始化一次
    */
   if (sharedInstance != null && args == null) {
      //打印的一些日志,不需要理会,其中  isSingletonCurrentlyInCreation 是判断单例bean是不是在创建中
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         } else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      /**
       * 1 sharedInstance 如果是个普通的单例bean,该方法会直接返回bean,
       * 2 sharedInstance 如果是个FactoryBean类型的,则需要调用 getObject 获取真正的FactoryBean然后返回《在这里,普通bean 和FactoryBean被一视同仁,只不过获取方式不大一样而已》
       */
      beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   } else {

      /**
       * 走到这里则说明 sharedInstance 可能是空,有2中可能性
       * 1 beanName对应的实例还没创建好,
       * 2 beanName对应的实例可能在父容器中创建了,需要再父容器查找
       */

      /**
       * BeanFactory 不会缓存Prototype类型的bean,直接抛出异常
       */
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      /**
       * 如果sharedInstance == null,先去父容器去查找
       */
      //获取父容器
      BeanFactory parentBeanFactory = getParentBeanFactory();
      /**
       * 如果父容器不为null, 且 beanDefinitionMap 不包含该bean
       */
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         /**
          * 获取 name 对应的 beanName,如果 name 是以 & 字符开头,则返回 & + beanName
          * 这里和上面有点区别,先是处理别名 然后如果该beanName是 factoryBean name的话,会把 & 还原
          */
         String nameToLookup = originalBeanName(name);
         /**
          * 如果父容器是  AbstractBeanFactory 或者其子类,
          */
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         } else if (args != null) {
            /**
             * 如果初始化参数不为null
             */
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         } else if (requiredType != null) {
            /**
             * 如果 requiredType 不为null
             */
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         } else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      /**
       * 如果 typeCheckOnly 参数为false, 标记该bean正在创建中
       */
      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
      try {
         if (requiredType != null) {
            beanCreation.tag("beanType", requiredType::toString);
         }
         /**
          * 合并父 BeanDefinition 与子 BeanDefinition
          */
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         /**
          * 检查是否有依赖,如果有的话,确保其依赖优先初始化
          * 该方法获取当前bean的依赖项
          */
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               /**
                * 检测是否存在 depends-on 循环依赖,若存在则抛异常。比如 A 依赖 B,B 又依赖 A,他们的配置如下:
                *   <bean id="beanA" class="BeanA" depends-on="beanB">
                *   <bean id="beanB" class="BeanB" depends-on="beanA">
                * beanA 要求 beanB 在其之前被创建,但 beanB 又要求 beanA 先于它
                * 创建。这个时候形成了循环,对于 depends-on 循环,Spring 会直接
                * 抛出异常
                *
                * 这里会有2个Map分别是 dependentBeanMap  dependenciesForBeanMap
                * dependentBeanMap key-> beanName, value -> 依赖该bean的所有bean集合   记录谁依赖当前bean
                * dependenciesForBeanMap  key-> beanName, value->该bean依赖的所有bean 集合 记录当前bean依赖谁
                * 思路清奇啊
                */
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               /**
                * 这一步主要是注册依赖记录,不然上一步的数据木得呀
                * 将当前beanName注册到   dependentBeanMap, 将dep注册到 dependenciesForBeanMap
                */
               registerDependentBean(dep, beanName);
               try {
                  /**
                   * 依次加载所依赖的bean,重复操作
                   */
                  getBean(dep);
               } catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         /**
          * 如果是单例bean
          */

         if (mbd.isSingleton()) {
            /**
             * 这里并没有直接调用 createBean 方法创建 bean 实例,而是通过 
             * getSingleton(String, ObjectFactory) 方法获取 bean 实例。
             * getSingleton(String, ObjectFactory) 方法会在内部调用 
             * ObjectFactory 的 getObject() 方法创建 bean,并会在创建完成后,
             * 将 bean 放入缓存中。关于 getSingleton 方法的分析,本文先不展开 后面的文章中进行分析
             */
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               } catch (BeansException ex) {
                  /**
                   * 发生异常的话 销毁bean
                   */
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            /**
             * 如果bean是FactoryBean, 则调用工厂方法获取真正的bean,单例则直接返回
             */
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         } else if (mbd.isPrototype()) {
            /**
             * 创建原型模式bean
             */
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            } finally {
               afterPrototypeCreation(beanName);
            }
            beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         } else {
            /**
             * 其他类型的bean
             */
            String scopeName = mbd.getScope();
            if (!StringUtils.hasLength(scopeName)) {
               throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
            }
            Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  } finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            } catch (IllegalStateException ex) {
               throw new ScopeNotActiveException(beanName, scopeName, ex);
            }
         }
      } catch (BeansException ex) {
         beanCreation.tag("exception", ex.getClass().toString());
         beanCreation.tag("message", String.valueOf(ex.getMessage()));
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      } finally {
         beanCreation.end();
      }
   }

   /**
    * 会做一些类型转换的事情
    */
   return adaptBeanInstance(name, beanInstance, requiredType);
}

个人觉得这2个beanMap很容易被搞混,这里特意贴出来,仅供参考

  • dependentBeanMap key-> beanName, value -> 依赖该bean的所有bean集合 记录谁依赖当前bean
  • dependenciesForBeanMap key-> beanName, value->该bean依赖的所有bean 集合 记录当前bean依赖谁

流程图如下

image.png

2 细节代码剖析

2.1 beanName转换


/**
 * 返回beanName
 * @param name
 * @return
 */
protected String transformedBeanName(String name) {
   return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}



/**
 * 如果 name 是以 & 开头,则截取后面返回,该操作主要是给FactoryBean做特殊处理,毕竟在BeanFactory中,FactoryBean和普通Bean无差
 * 比如 name = "&&&&&person",最终会被转成 person
 * @param name
 * @return
 */
public static String transformedBeanName(String name) {
   Assert.notNull(name, "'name' must not be null");
   if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
      return name;
   }
   return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
      do {
         beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
      }
      while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
      return beanName;
   });
}

/**
 * 主要是出路别名,里面有循环
 * 这里使用 while 循环进行处理,原因是:可能会存在多重别名的问题,即别名指向别名。比如下面的配置:
 * <bean id="hello1" class="service.Hello"/>
 * <alias name="hello1" alias="aliasA1"/>
 * <alias name="aliasA1" alias="aliasB"/>
 * <p>
 * 上面的别名指向关系为 aliasB -> aliasA1 -> hello1,对于上面的别名配置,aliasMap 中数据
 * 视图为:aliasMap = [<aliasB, aliasA1>, <aliasA1, hello1>]。通过下面的循环解析别名
 * aliasB 最终指向的 hello1
 *
 * @param name
 * @return
 */
public String canonicalName(String name) {
   String canonicalName = name;
   String resolvedName;
   do {
      resolvedName = this.aliasMap.get(canonicalName);
      if (resolvedName != null) {
         canonicalName = resolvedName;
      }
   }
   while (resolvedName != null);
   return canonicalName;
}

2.2 从缓存中获取bean getSingleton

我们都知道, 对于单例 Bean Spring 只会实例化一次,那么如何保证多次获取bean的时候返回的都是同一个呢?答案就是 缓存, 当然这里说的缓存和 Redis 没有半毛钱关系哈! 废话不多说,上代码

@Override
@Nullable
public Object getSingleton(String beanName) {
   return getSingleton(beanName, true);
}

/**
 *
 * @param beanName
 * @param allowEarlyReference 是否允许其他bean引用正在创建的bean, 同时也是解决循环依赖的关键点
 * @return
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   /**
    * singletonObjects 是 ConcurrentHashMap 结构,key->beanName, value->bean
    */
   Object singletonObject = this.singletonObjects.get(beanName);
   /**
    * 如果 singletonObject==null 表名未创建,或者正在创建中
    *
    */
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      /**
       * 从 earlySingletonObjects 中获取提前曝光的 bean,用于处理循环引用
       */
      singletonObject = this.earlySingletonObjects.get(beanName);
      /**
       * 如果 singletonObject==null, 且允许提前曝光bean
       */
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  /**
                   * 从bean工厂缓存中获取对应 工厂类
                   */
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     /**
                      * 如果工厂类不为null 直接获取且赋值给  singletonObject
                      * 将 singletonObject 放到  earlySingletonObjects 这个缓存中,可以解决后续的循环依赖
                      * 同时将beanFacotry移除,后续不会在用到了
                      */
                     singletonObject = singletonFactory.getObject();
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

上述代码中有3个缓存集合,是面试中的重点,我们简单说说

缓存名用途
singletonObjects用于存放完全初始化完成后的bean,可以直接使用
earlySingletonObjects用于存放还在初始化中的bean,用于解决循环依赖
singletonFactories用户存放bean工厂,bean工厂所产生的bean还未完全初始化号,其所生成的bean下一步会被放在 earlySingletonObjects

2.3 合并父子BeanDefinition

相信有部分胖友和我一样,对bean的合并 getMergedLocalBeanDefinition 有点摸不着头脑,其实我们说的父子 BeanDefinition 如下配置, stu 继承了person,可以覆盖父类中的配置

<bean id="person" class="com.fenghuolun.spring.nazha.bean.Person">
    <property name="content" value="tec"/>
</bean>

<bean id="stu" parent="person">
    <property name="content" value="child"/>

</bean>

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
   // 检测 mergedBeanDefinitions 是否已经包含了beanName对应的bean,如果已包含,直接返回
   RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
   if (mbd != null && !mbd.stale) {
      return mbd;
   }
   //调用重载方法
   return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}


protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
      throws BeanDefinitionStoreException {

   return getMergedBeanDefinition(beanName, bd, null);
}

/**
 *
 * @param beanName
 * @param bd
 * @param containingBd
 * @return
 * @throws BeanDefinitionStoreException
 */
protected RootBeanDefinition getMergedBeanDefinition(
      String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
      throws BeanDefinitionStoreException {
   //同步锁
   synchronized (this.mergedBeanDefinitions) {
      RootBeanDefinition mbd = null;
      RootBeanDefinition previous = null;

      // containingBd 如果是null, 则 从缓存获取对应的baen赋值给 mbd
      if (containingBd == null) {
         mbd = this.mergedBeanDefinitions.get(beanName);
      }

      if (mbd == null || mbd.stale) {
         previous = mbd;
         //如果 bd.getParentName()==null,说明无父配置,直接将当前的 BeanDefinition 升级为 RootBeanDefinition
         if (bd.getParentName() == null) {
            // 用bean
            if (bd instanceof RootBeanDefinition) {
               mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
            } else {
               mbd = new RootBeanDefinition(bd);
            }
         } else {

            BeanDefinition pbd;
            try {
               /**
                * 通过老方法获取beanName
                */
               String parentBeanName = transformedBeanName(bd.getParentName());
               /**
                * 判断父类beanName和子类BeanName是否相同,如果相同,说明父类bean一定在父容器中(因为容器底层采用的Map,key是唯一的)
                *
                */
               if (!beanName.equals(parentBeanName)) {
                  /**
                   * 再次调用 getMergedBeanDefinition,参数值未parentBeanName,用于合并父 BeanDefinition 和爷爷辈的BeanDefinition。
                   * 如果爷爷辈的 BeanDefinition 仍有父BeanDefinition,则继续合并
                   */
                  pbd = getMergedBeanDefinition(parentBeanName);
               } else {
                  /**
                   * 获取父容器,并判断,父容器的类型,若不是 ConfigurableBeanFactory 则判抛出异常
                   */
                  BeanFactory parent = getParentBeanFactory();
                  if (parent instanceof ConfigurableBeanFactory) {
                     pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                  } else {
                     throw new NoSuchBeanDefinitionException(parentBeanName,
                           "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                 "': cannot be resolved without a ConfigurableBeanFactory parent");
                  }
               }
            } catch (NoSuchBeanDefinitionException ex) {
               throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                     "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
            }
            /**
             *  以父 BeanDefinition 的配置信息为蓝本创建 RootBeanDefinition,也就是“已合并的 BeanDefinition”
             *  同时用 子 BeanDefinition 中的属性覆盖父 BeanDefinition 中的属性
             */
            mbd = new RootBeanDefinition(pbd);
            mbd.overrideFrom(bd);
         }

         /**
          * 如果用户未配置scope属性,默认单例模式
          */
         if (!StringUtils.hasLength(mbd.getScope())) {
            mbd.setScope(SCOPE_SINGLETON);
         }

         /**
          * 改写 mdb的 scope属性
          */
         if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
            mbd.setScope(containingBd.getScope());
         }

         
         if (containingBd == null && isCacheBeanMetadata()) {
            this.mergedBeanDefinitions.put(beanName, mbd);
         }
      }
      if (previous != null) {
         copyRelevantMergedBeanDefinitionCaches(previous, mbd);
      }
      return mbd;
   }
}

2.4 从 FactoryBean 中获取 bean 实例


protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   // 如果name以 & 开头
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      if (beanInstance instanceof NullBean) {
         return beanInstance;
      }
      //如果 beanInstance 不是FactoryBean 抛出异常
      if (!(beanInstance instanceof FactoryBean)) {
         throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
      }
      //设置mbd 为工厂Bean
      if (mbd != null) {
         mbd.isFactoryBean = true;
      }
      return beanInstance;
   }

   /**
    * 到了这一步,beanInstance 要么是工厂bean 要么是普通bean, 如果是普通bean直接返回
    */
   if (!(beanInstance instanceof FactoryBean)) {
      return beanInstance;
   }

   //后续流程中 beanInstance 肯定是个 FactoryBean
   Object object = null;
   if (mbd != null) {
      mbd.isFactoryBean = true;
   } else {
      /**
       * 如果 mbd 为null(从 getBean方法进来的话, mbd肯定是null哈),从缓存中获取beanName对应的FactoryBean
       * FactoryBean生成的单例bean都放在 factoryBeanObjectCache 这个Map中
       */
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {
      //如果 object == null, 将 beanInstance 转化为 FactoryBean
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      // 合并 BeanDefinition
      if (mbd == null && containsBeanDefinition(beanName)) {
         mbd = getMergedLocalBeanDefinition(beanName);
      }
      /**
       * synthetic 字面意思是"合成的",这个字段还不大清楚是啥意思
       */
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      // 调用 getObjectFromFactoryBean 方法继续获取实例
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}



protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   /**
    * 如果 factory是单例模式 且 singletonObjects 包含beanName,
    * 注意 FactoryBean也有单例模式和非单例模式,和普通Bean没有区别
    */
   if (factory.isSingleton() && containsSingleton(beanName)) {
      synchronized (getSingletonMutex()) {
         //缓存中获取bean
         Object object = this.factoryBeanObjectCache.get(beanName);
         if (object == null) {
            //bean == null ,使用工厂获取bean
            object = doGetObjectFromFactoryBean(factory, beanName);

            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
            if (alreadyThere != null) {
               object = alreadyThere;
            }
            else {
               //如果是 !synthetic
               if (shouldPostProcess) {
                  //当前bean正在创建中,直接返回
                  if (isSingletonCurrentlyInCreation(beanName)) {
                     return object;
                  }
                  // 添加到 singletonsCurrentlyInCreation
                  beforeSingletonCreation(beanName);
                  try {
                     //后置处理,这里没有做啥事情其实
                     object = postProcessObjectFromFactoryBean(object, beanName);
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
                  finally {
                     //从  singletonsCurrentlyInCreation 移除
                     afterSingletonCreation(beanName);
                  }
               }
               //FactoryBean 所创建的实例会被缓存在 factoryBeanObjectCache 中,供后续调用使用
               if (containsSingleton(beanName)) {
                  this.factoryBeanObjectCache.put(beanName, object);
               }
            }
         }
         return object;
      }
   }
   else {
      Object object = doGetObjectFromFactoryBean(factory, beanName);
      if (shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;
   }
}

需要重点关注下beforeSingletonCreationafterSingletonCreation


protected void beforeSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}



protected void afterSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
   }
}

细心的胖友会发现singletonsCurrentlyInCreation 这个缓存又被用到哦 具体作用是啥,上门有具体的说明。这里就不多做赘述了。