likes
comments
collection
share

Spring5源码7-Bean创建及初始化(上)

作者站长头像
站长
· 阅读数 18

欢迎大家关注 github.com/hsfxuebao ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈

本文主要分析bean的创建过程。

1. refresh()

// 容器刷新的十二大步骤
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
         ...

         // Instantiate all remaining (non-lazy-init) singletons.
         // 11. 【大核心】bean创建:完成BeanFactory 初始化(工厂里面所有的组件都好了)
         /*
          * 这个方法一定要理解要具体看
          * 1、bean实例化过程
          * 2、ioc
          * 3、注解支持
          * 4、BeanPostProcessor的执行
          * 5、Aop的入口
          */
         finishBeanFactoryInitialization(beanFactory);

         ...
      }
      ...
   }
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   ...
   // Instantiate all remaining (non-lazy-init) singletons.
   // 初始化所有 非懒加载的单实例的bean
   beanFactory.preInstantiateSingletons();
}
public void preInstantiateSingletons() throws BeansException {
   ...
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   // 创建出所有的单实例bean
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      // 单实例 & 非抽象&不是懒加载
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         // 如果是FactoryBean
         if (isFactoryBean(beanName)) {
            //
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged(
                        (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         // 不是FactoryBean则执行这个逻辑,普通的单实例非懒加载bean的创建
         else {
            // todo
            getBean(beanName);
         }
      }
   }

我们知道了 Spring 在容器刷新的后期 通过调用AbstractApplicationContext#finishBeanFactoryInitialization 方法来实例化了所有的非惰性bean。在这里面就通过 beanFactory.preInstantiateSingletons(); 调用了一个非常关键的方法 AbstractBeanFactory#getBean(java.lang.String),而其实际上调用的是 AbstractBeanFactory#doGetBean 方法。

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

如果说,Spring中,Bean 的发现是在 ConfigurationClassPostProcessor 中进行的。那么Bean的创建就是在 doGetBean方法中进行的。 doGetBean 完成了单例Bean的完整创建过程,包括bean的创建,BeanPostProcessor 的方法调用、init-method等方法的调用、Aware 等接口的实现。下面,我们开始来分析这个 doGetBean。

关于Bean 的加载过程,AbstractApplicationContext#finishBeanFactoryInitialization 经过几次跳转,最终会跳转到 AbstractBeanFactory#doGetBean 方法。每个bean的创建都会经历此方法,所以本文的主要内容是分析 AbstractBeanFactory#doGetBean

2. DefaultListableBeanFactory

需要强调的是,本文中调用 doGetBean 方法的是 AbstractBeanFactory 的子类DefaultListableBeanFactory。如下图:

Spring5源码7-Bean创建及初始化(上)

DefaultListableBeanFactory 结构图如下:

Spring5源码7-Bean创建及初始化(上)

DefaultListableBeanFactory 是 Spring默认的BeanFactory类型。

注意这里说的 BeanFactory 并不是指 ApplicationContext,而是 ApplicationContext 内部的一个BeanFactory

2.1 DefaultSingletonBeanRegistry

在这里我们只需要知道DefaultListableBeanFactory 继承了 DefaultSingletonBeanRegistry类,拥有了 DefaultSingletonBeanRegistry 一系列的 集合类型来保存Bean相关信息。

大体如下,其中我们主要只需要关注前四个即可:

    /** Cache of singleton objects: bean name to bean instance. */
    //	用于保存BeanName和创建bean实例之间的关系,即缓存bean。 beanname -> instance 
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** Cache of singleton factories: bean name to ObjectFactory. */
    // 用于保存BeanName和常见bean的工厂之间的关系。beanname-> ObjectFactory
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /** Cache of early singleton objects: bean name to bean instance. */
    // 也是保存BeanName和创建bean实例之间的关系,与singletonObjects 不同的是,如果一个单例bean被保存在此,则当bean还在创建过程中(比如 A类中有B类属性,当创建A类时发现需要先创建B类,这时候Spring又跑去创建B类,A类就会添加到该集合中,表示正在创建),就可以通过getBean方法获取到了,其目的是用来检测循环引用。
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    /** Set of registered singletons, containing the bean names in registration order. */
    // 用来保存当前所有已经注册的bean
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

    /** Names of beans that are currently in creation. */
    // 用来保存当前正在创建的Bean。也是为了解决循环依赖的问题
    private final Set<String> singletonsCurrentlyInCreation =
                    Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    /** Names of beans currently excluded from in creation checks. */
    // 用来保存当前从创建检查中排除的bean名称
    private final Set<String> inCreationCheckExclusions =
                    Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    /** List of suppressed Exceptions, available for associating related causes. */
    // 初始化过程中的异常列表
    @Nullable
    private Set<Exception> suppressedExceptions;

    /** Flag that indicates whether we're currently within destroySingletons. */
    // 标志是否在销毁BeanFactory过程中
    private boolean singletonsCurrentlyInDestruction = false;

    /** Disposable bean instances: bean name to disposable instance. */
    // 一次性bean实例:beanName -> 一次性实例。暂未明白
    private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

    /** Map between containing bean names: bean name to Set of bean names that the bean contains. */
    // 包含的Bean名称之间的映射:BeanName  -> Bean包含的BeanName集合
    private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

    /** Map between dependent bean names: bean name to Set of dependent bean names. */
    // bean dependent(依赖的集合) : beanName -> 依赖该beanName 的 bean,即 key代表的bean 被value 所依赖
    private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

    /** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
    // bean 被哪些bean依赖 :  beanName -> beanName 所依赖的 bean。即 key 依赖于value这些bean
    private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

2.1.1 关键缓存

下面挑出来几个关键缓存集合来描述:

  • singletonObjects :ConcurrentHashMap。最简单最重要的缓存Map。保存关系是 beanName :bean实例关系。单例的bean在创建完成后都会保存在 singletonObjects 中,后续使用直接从singletonObjects 中获取。
  • singletonFactories :HashMap。这是为了解决循环依赖问题,用于提前暴露对象,保存形式是 beanName : ObjectFactory<?>
  • earlySingletonObjects :HashMap。这也是为了解决循环依赖问题。和 singletonFactories 互斥。因为 singletonFactories 保存的是 ObjectFactory。而earlySingletonObjects 个人认为是 singletonFactories 更进一步的缓存,保存的是 ObjectFactory#getObject的结果。
  • registeredSingletons :LinkedHashSet,用于保存注册过的beanName。
  • singletonsCurrentlyInCreation : 保存当前正在创建的bean。当一个bean开始创建时将保存其beanName,创建完成后将其移除
  • dependentBeanMap :保存bean的依赖关系,比如A对象依赖于 B对象,会出现 B :A。即保存的是key 被value依赖
  • dependenciesForBeanMap :保存bean的依赖关系,不过和dependentBeanMap 反了过来。A对象依赖于 B对象,会出现 A :B。保存的是key 依赖于 value

我们拿一个简单的场景解释一下 singletonFactoriesearlySingletonObjects 的关系 。 下面的代码是 DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean) 。我们可以看到其判断逻辑,

  • 锁定 singletonObjects,毕竟要操作 singletonObjects

  • singletonFactories 中获取 ObjectFactory 缓存

  • 如果存在 ObjectFactory 缓存,则更进一步提取ObjectFactory#getObjectsingletonObject 对象。将singletonObject 保存到 earlySingletonObjects 缓存中,同时从 singletonFactories 中移除。

// DCL
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   // 检查单例缓存池 中有没有
   Object singletonObject = this.singletonObjects.get(beanName);  // 以及缓存
   // 如果当前bean正在创建中,而且缓存中没有则继续
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            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;
}

2.1.2 图解

补上一张图,来看一看 A,B循环依赖 singletonFactoriesearlySingletonObjects 的变化

Spring5源码7-Bean创建及初始化(上)

在创建过程中会被添加到 singletonFactories 中,但当bean被循环依赖时会被添加到 earlySingletonObjects 中。也即是说 earlySingletonObjects 中的bean都是被循环依赖的。

2.2 BeanDefinition

这里简单介绍一下,顾名思义,BeanDefinition是bean的信息,一个BeanDefinition 描述和定义了创建一个bean需要的所有信息,属性,构造函数参数以及访问它们的方法。还有其他一些信息,比如这些定义来源自哪个类等等。

对于XML 配置方式的Spring方式来说, BeanDefinition 是配置文件 < bean > 元素标签在容器中的内容表示形式。<bean> 元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition 则提供了相应的beanClass、scope、lazyinit属性,BeanDefinition 和 <bean> 中的属性是一一对应的。其中RootBeanDefinition 是最常用的实现类,一般对应< bean > 元素标签。

类似下图的定义:

Spring5源码7-Bean创建及初始化(上) 需要注意的是 BeanDefinition 是一个接口,在Spring 中存在多种实现,具体请参考:blog.csdn.net/andy_zhang2… www.cnblogs.com/loongk/p/12…

3. doGetBean:bean的加载

下面我们开始进入正题,进行 AbstractBeanFactory#doGetBean的内容分析。这个方法是一切的核心(Bean的创建过程也是在这个方法中完成)。首先我们先来整体过一遍方法代码。后面将会对一些关键点进行详细解释。

protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {

   // 1. 提取出对应的beanName。会去除一些特殊的修饰符比如 "&"
   String beanName = transformedBeanName(name);
   Object beanInstance;

   // Eagerly check singleton cache for manually registered singletons.
   // 2. 尝试从缓存获取或者singletonFacotries中的ObjectFactory中获取。后续细讲
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      ...
      // 3. 返回对应的实例,有时候存在诸如FactoryBean的情况并不直接返回实例本身,
      // 而是返回指定方法返回的实例。这一步主要还是针对FactoryBean的处理。
      beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   } // 默认第一次获取组件都会走到else中
   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      // 4. 只有单例情况才会尝试解决循环依赖,原型模式直接抛出异常。因为原型模式无法解决循环依赖问题。
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      // 拿到整个BeanFactory的父工厂,从父工厂中尝试获取组件
      BeanFactory parentBeanFactory = getParentBeanFactory();
      // 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         // 递归到BeanFactory中检测
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         }
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      // 如果不仅仅做类型检查则是创建bean,这里需要记录
      if (!typeCheckOnly) {
         // 这里是将 当前创建的beanName 保存到 alreadyCreated 集合中。
         // alreadyCreated 中的bean表示当前bean已经创建了,在进行循环依赖判断的时候会使用
         markBeanAsCreated(beanName);
      }

      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
      try {
         if (requiredType != null) {
            beanCreation.tag("beanType", requiredType::toString);
         }
         // 6. 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         // 7. 寻找bean的依赖: 获取初始化的依赖项
         String[] dependsOn = mbd.getDependsOn();
         // 如果需要依赖,则递归实例化依赖bean
         if (dependsOn != null) {
            // 看当前的bean 有没有依赖 其他Bean
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  // 依赖了其他Bean,就先获取其他的Bean
                  getBean(dep);
               }
               ...
            }
         }

         // Create bean instance.  创建bean的实例
         // 8 针对不同的Scope 进行bean的创建
         // 实例化依赖的bean便可以实例化mdb本身了
         // singleton 模式的创建
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  // todo 创建bean实例
                  return createBean(beanName, mbd, args);
               }
              ...
            });
            // 检查当前bean是否是 FactoryBean
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            // Prototype 模式的创建
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         else {
            // 指定scope上实例化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);
            }
         }
      }
      ...
      finally {
         beanCreation.end();
      }
   }
   // 9 类型转换, 转Object为bean信息
   return adaptBeanInstance(name, beanInstance, requiredType);
}

@SuppressWarnings("unchecked")
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
   // Check if required type matches the type of the actual bean instance.
   // 检查需要的类型是否符合bean 的实际类型
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return (T) convertedBean;
      }
      ...
   }
   return (T) bean;
}

综上所属,doGetBean的 大体流程如下:

  1. 将传入的beanName 转化为合适的beanName。因为这里可能传入bean的别名,比如 FactoryBean 这里就是传入 “&beanName” , 这一步就会将其转化为 “beanName”
  2. 尝试从单例缓存中获取 bean,主要是尝试从 singletonObjectssingletonFactories 中获取实例。(这一步中还使用了 earlySingletonObjects 来判断循环依赖的问题)
  3. 如果第二步获取到了bean,则会针对处理 FactoryBean 这种特殊情况,以获取到正确的bean。(因为Factorybean 的话可能需要将其 getObject 方法的返回值作为bean注入到容器中)。
  4. 如果第二步没有获取到bean,则会检测其原型模式下的循环依赖情况,如果原型模式下有循环依赖,则直接抛出异常,因为原型模式下无法解决循环依赖。
  5. 如果第四步没有抛出异常,则会判断 当前BeanFactory 中是否包含该beanName 的定义信息,如果不包含,则会递归去 parentBeanFactory 中去寻找beanName的定义信息.
  6. 随后查询beanName 的 BeanDefinition 是否具有 父类的BeanDefinition, 如果有,则将 父类的一些属性和子类合并,形成一个新的BeanDefinition : mdb
  7. 获取mdb中的 depends-on 属性,优先将依赖的bean创建,随后再创建当前bean。
  8. 到这一步,则说明当前bean尚未创建,则会根据 singleton 或者 prototype 或其他逻辑,走不同的流程来创建bean
  9. 创建bean结束后,根据调用者需要的类型进行一个类型转换。比如调用者希望返回一个Integer,这里得到的结果却是String,则会进行一个类型的转换。

3.1 转换 beanName

final String beanName = transformedBeanName(name);

这一步的目的是为了去除 beanName 的别名,获取bean的真正beanName。

这里的name传入的可能是 bean的别名,或者是FactoryBean类型的bean。所以需要一系列的解析,解析包括:

  • 去除 FactoryBean 的修饰符。也就是说如果 name = “&name” 或者 name = “&&name” 这种多&& 情况也会去除& 使得 name = “name”。

  • 取指定alias所表示的最终beanName。比如别名A指向B的bean,则会返回B。

代码如下:

protected String transformedBeanName(String name) {
        return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

....
// 从别名中获取真正的beanName
public String canonicalName(String name) {
        String canonicalName = name;
        // Handle aliasing...
        String resolvedName;
        do {
                // 从aliasMap 中获取到真实的beanName
                resolvedName = this.aliasMap.get(canonicalName);
                if (resolvedName != null) {
                        canonicalName = resolvedName;
                }
        }
        while (resolvedName != null);
        return canonicalName;
}

....
// BeanFactoryUtils 中
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;
        });
}

3.2 尝试从缓存中加载单例

    Object sharedInstance = getSingleton(beanName);

对于单例Bean来说, Spring只会在同一容器中创建一次,并将创建好的Bean 实例保存到 singletonObjects 中,下次再获取bean实例,直接从 singletonObjects 中获取。

这一步的目的是从尝试从缓存中获取实例。需要注意的是,Spring为了解决循环依赖问题, 在创建bean的原则是不等bean 创建完成就会将创建bean的ObjectFactory提早曝光加入到singletonFactories缓存中,一旦下一个bean创建时需要依赖上一个bean,则直接使用ObjectFactory。 关于循环依赖的更多问题,后面会介绍。

代码逻辑如下:

  1. 尝试从singletonObjects 中获取Bean 实例。获取不到说明该bean尚未创建成功
  2. isSingletonCurrentlyInCreation 返回 true,则说明当前bean 的创建过程存在循环依赖。下面的逻辑就是为了尝试解决循环依赖
  3. 尝试从 earlySingletonObjects 中获取,获取不到说明该bean并未在创建过程中。(为了解决循环依赖的问题)
  4. allowEarlyReference = true时,这个是针对循环引用的操作,是允许循环引用。
  5. 随后 从singletonFactories 中加载 ObjectFactory,并将结果保存到 earlySingletonObjects 中,同时将 singletonFactories 中关于bean的定义移除。(earlySingletonObjects 和 singletonFactories 互斥)

这里我们看到

  • singletonFactories 的映射关系是 beanName : ObjectFactory
  • earlySingletonObjects 的映射关系是 beanName : ObjectFactory#getObject

earlySingletonObjectssingletonFactories 更进一步的缓存,所以二者互斥,相同的对象,一个缓存中存在即可。

具体代码如下:

// DCL
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   // 检查单例缓存池 中有没有
   Object singletonObject = this.singletonObjects.get(beanName);  // 以及缓存
   // 如果当前bean正在创建中,而且缓存中没有则继续
   // 单例缓存中没有对象 && 当前单例bean正在创建中,这是为了解决循环依赖的问题
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 如果此时bean正在加载(bean 在 earlySingletonObjects 中),则直接将singletonObject 返回。
      singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
      // allowEarlyReference = true 才会允许循环依赖
      if (singletonObject == null && allowEarlyReference) {
         // 如果单例缓存中不存在该bean,则加锁进行接下来的处理
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  // 当某些方法需要提前初始化的时候则会调用addSingletonFactory
                  // 将对应的ObjectFactory初始化策略存储在singletonFactories中
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);  // 三级缓存
                  if (singletonFactory != null) {
                     // 调用预先设定的getObject方法
                     singletonObject = singletonFactory.getObject();
                     // 记录在缓存中,earlySingletonObjects 和 singletonFactories互斥
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

3.3 尝试从FactoryBean中获取对象

    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

当我们结束上一步之后,经过 sharedInstance != null && args == null 的判断后就会调用该方法。作为上一步获取到的结果 sharedInstance 。我们需要判断其是否是 FactoryBean 的 实现类,如果是,则需要将其getObject() 的结果注入。所以该方法的功能简单来说就是用来检测当前bean是否是FactoryBean类型的bean,如果是,则调用其getObject() 方法,并将其返回值作为bean。

代码逻辑大体如下:

  1. 首先是在 AbstractBeanFactory#getObjectForBeanInstance 中 判断程序是否想获取 FactoryBean实例(beanName 是否以 & 开头)。如果是判断当前beanInstance是否是 FactoryBean。如果是则返回,否则抛出异常
  2. 如果不是想获取FactoryBean,那么就是想获取bean实例了。那么判断此时的beanInstance是普通的bean还是FactoryBean类型,如果是普通的bean则直接返回。
  3. 此时beanInstance 必定是 FactoryBean类型并且程序想获取bean实例。那么首先尝试从缓存 factoryBeanObjectCache 中获取。获取失败,则调用FactoryBean#getObject 方法来获取bean实例。并且在允许调用后置方法的情况下(shouldPostProcess 为true),调用BeanPostProcessor#postProcessAfterInitialization 的方法。

下面我们来看详细代码

3.3.1 AbstractBeanFactory#getObjectForBeanInstance

调用了 AbstractBeanFactory#getObjectForBeanInstance:

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

        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        // 1. 检测name 是否是想获取 工厂类 (name 以 & 开头) 
        if (BeanFactoryUtils.isFactoryDereference(name)) {
                if (beanInstance instanceof NullBean) {
                        return beanInstance;
                }
                // 以&开头又不是FactoryBean实现类,则抛出异常
                if (!(beanInstance instanceof FactoryBean)) {
                        throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
                }
                if (mbd != null) {
                        mbd.isFactoryBean = true;
                }
                return beanInstance;
        }

        // 2. 此时bean可能是 FactoryBean 或者 普通的bean。判断如果 beanInstance 不是 FactoryBean而是普通的bean, 就直接返回
        if (!(beanInstance instanceof FactoryBean)) {
                return beanInstance;
        }
        // 3. 到这一步就可以确定,当前beanInstance 是FactoryBean,并且需要获取getObject() 的结果
        Object object = null;
        if (mbd != null) {
                mbd.isFactoryBean = true;
        }
        else {
                // 尝试从缓存中加载bean。这一步是从 factoryBeanObjectCache 集合中获取
                // 在后面获取 bean 成功后,可能会将 其缓存到 factoryBeanObjectCache  中
                object = getCachedObjectForFactoryBean(beanName);
        }

        if (object == null) {
                // Return bean instance from factory.
                FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
                // containsBeanDefinition 检测  beanDefinitionMap中也就是所有已经加载的类中检测是否定义beanName
                if (mbd == null && containsBeanDefinition(beanName)) {
                        // 合并父类bean 定义的属性
                        mbd = getMergedLocalBeanDefinition(beanName);
                }
                boolean synthetic = (mbd != null && mbd.isSynthetic());
                // 4. 这一步中对FactoryBean进行了解析。
                object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
}

3.3.1.1 doGetObjectFromFactoryBean

getObjectFromFactoryBean 方法中 调用 doGetObjectFromFactoryBean 方法来获取 FactoryBean 中的 bean实例。下面我们来看一下getObjectFromFactoryBean 代码:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        // 判断是否是单例模式 && singletonObjects 尚未缓存该bean (containsSingleton调用的是 singletonObjects )
        if (factory.isSingleton() && containsSingleton(beanName)) {
                synchronized (getSingletonMutex()) {
                        // 尝试从 factoryBeanObjectCache 缓存中获取
                        Object object = this.factoryBeanObjectCache.get(beanName);
                        if (object == null) {
                                // 在这个方法中进行解析。调用 FactoryBean 的 getObject 方法
                                object = doGetObjectFromFactoryBean(factory, beanName);

                                // 因为是单例模式,所以要保证变量的全局唯一。所以这里如果缓存中已经创建好了bean则替换为已经创建好的bean
                                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                                if (alreadyThere != null) {
                                        object = alreadyThere;
                                }
                                else {
                                        // 如果允许调用bean的后置处理器。因为这里是直接将bean创建返回了,如果要调用后置方法则只能在这里调用。
                                        if (shouldPostProcess) {
                                                if (isSingletonCurrentlyInCreation(beanName)) {
                                                        // Temporarily return non-post-processed object, not storing it yet..
                                                        return object;
                                                }
                                                // 将beanName 添加到 singletonsCurrentlyInCreation 中缓存,表示当前bean正在创建中
                                                beforeSingletonCreation(beanName);
                                                try {
                                                        // 调用了ObjectFactory的后置处理器。
                                                        object = postProcessObjectFromFactoryBean(object, beanName);
                                                }
                                                catch (Throwable ex) {
                                                        throw new BeanCreationException(beanName,
                                                                        "Post-processing of FactoryBean's singleton object failed", ex);
                                                }
                                                finally {
                                                // 将beanName 从 singletonsCurrentlyInCreation 中移除,表示当前bean已经创建结束
                                                        afterSingletonCreation(beanName);
                                                }
                                        }
                                        // return this.singletonObjects.containsKey(beanName); 如果 singletonObjects缓存中存在当前beanName,则将其缓存到 factoryBeanObjectCache 中。
                                        if (containsSingleton(beanName)) {
                                                // 这里保存的是 beanName : FactoryBean
                                                this.factoryBeanObjectCache.put(beanName, object);
                                        }
                                }
                        }
                        return object;
                }
        }
        else {
                // FactoryBean 非单例直接调用 getObject 方法
                Object object = doGetObjectFromFactoryBean(factory, beanName);
                // 如果允许调用后置方法,则调用postProcessObjectFromFactoryBean 方法
                if (shouldPostProcess) {
                        try {
                                object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                        }
                }
                return object;
        }
}

3.4 原型模式的依赖检查 - isPrototypeCurrentlyInCreation

if (isPrototypeCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
}

后面会对循环依赖进行详细介绍,简而言之就是 单例模式下才会尝试去解决循环依赖的问题,而原型模式则无法解决。也就是 isPrototypeCurrentlyInCreation 返回true,则抛出异常。

需要注意的是还有一个 方法是 判断单例模式的依赖检查 : isSingletonCurrentlyInCreation

3.5 递归 parentBeanFactory

这一步的逻辑比较简单,如下:

  1. 首先通过 containsBeanDefinition(beanName) 方法判断当前beanFactory中是否有bean的定义,如果有,皆大欢喜。直接进入下一步。
  2. 如果没有,且 parentBeanFactory 不为空,则会通过递归的方式,尝试从 parentBeanFactory 中加载bean定义。
// 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // Not found -> check parent.
        // 递归到BeanFactory中检测
        String nameToLookup = originalBeanName(name);
        if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                                nameToLookup, requiredType, args, typeCheckOnly);
        }
        else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
        }
        else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
        else {
                return (T) parentBeanFactory.getBean(nameToLookup);
        }
}

其中 DefaultListableBeanFactory#containsBeanDefinition 代码如下

@Override
public boolean containsBeanDefinition(String beanName) {
        Assert.notNull(beanName, "Bean name must not be null");
        return this.beanDefinitionMap.containsKey(beanName);
}

3.6 合并 BeanDefinition

BeanDefinition 顾名思义,就是关于bean 的定义信息。通过xml的bean定义可以很清楚的看到一些属性定义。

所以这一步就是检查当前 BeanDefinition 是否有父BeanDefinition ,如果有将一些属性和当前bean合并,生成一个 RootBeanDefinition。

推荐阅读: blog.csdn.net/andy_zhang2…

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

这一块的调用链路:getMergedLocalBeanDefinition -> getMergedBeanDefinition -> getMergedBeanDefinition。所以我们 这里直接来看 getMergedBeanDefinition 方法。

首先,mdb 即 MergedBeanDefinition 的缩写,即一个合并的beanDefinition。

// 如果给定bean的定义是子bean定义,则通过与父级合并返回RootBeanDefinition。
protected RootBeanDefinition getMergedBeanDefinition(
                String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
                throws BeanDefinitionStoreException {

        synchronized (this.mergedBeanDefinitions) {
                RootBeanDefinition mbd = null;
                RootBeanDefinition previous = null;

                // Check with full lock now in order to enforce the same merged instance.
                if (containingBd == null) {
                        mbd = this.mergedBeanDefinitions.get(beanName);
                }

                if (mbd == null || mbd.stale) {
                        previous = mbd;
                        // 判断如果parentName为空则没必要进行合并了,直接克隆返回即可
                        if (bd.getParentName() == null) {
                                // Use copy of given root bean definition.
                                if (bd instanceof RootBeanDefinition) {
                                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                                }
                                else {
                                        mbd = new RootBeanDefinition(bd);
                                }
                        }
                        else {
                                // Child bean definition: needs to be merged with parent.
                                BeanDefinition pbd;
                                try {
                                        // 转换beanName
                                        String parentBeanName = transformedBeanName(bd.getParentName());
                                        // 递归调用,解析更上层的parent BeanDefinition 
                                        if (!beanName.equals(parentBeanName)) {
                                                pbd = getMergedBeanDefinition(parentBeanName);
                                        }
                                        else {
                                                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);
                                }
                                // Deep copy with overridden values.
                                // 深拷贝
                                mbd = new RootBeanDefinition(pbd);
                                mbd.overrideFrom(bd);
                        }

                        // Set default singleton scope, if not configured before.
                        if (!StringUtils.hasLength(mbd.getScope())) {
                                mbd.setScope(SCOPE_SINGLETON);
                        }

                        if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                                mbd.setScope(containingBd.getScope());
                        }

                        // Cache the merged bean definition for the time being
                        // (it might still get re-merged later on in order to pick up metadata changes)
                        if (containingBd == null && isCacheBeanMetadata()) {
                                this.mergedBeanDefinitions.put(beanName, mbd);
                        }
                }
                if (previous != null) {
                        copyRelevantMergedBeanDefinitionCaches(previous, mbd);
                }
                return mbd;
        }
}

3.7 寻找依赖

这一步也是针对 BeanDefinitiondependsOn 属性来说的(对应注解则是 @DependsOn。主要是 优先加载Bean 的 depends-on依赖。

注:在 BeanDefinition 加载过程中,通过扫描路径加载的时候,通过 ClassPathBeanDefinitionScanner#doScan方法时会调用AnnotationConfigUtils#processCommonDefinitionAnnotations 来进行BeanDefinition 封装,其中就包含了诸多注解的解析,如下:

// 解读所有bean定义信息需要感知的注解
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
   AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
   if (lazy != null) {
      abd.setLazyInit(lazy.getBoolean("value"));
   }
   else if (abd.getMetadata() != metadata) {
      lazy = attributesFor(abd.getMetadata(), Lazy.class);
      if (lazy != null) {
         abd.setLazyInit(lazy.getBoolean("value"));
      }
   }

   if (metadata.isAnnotated(Primary.class.getName())) {
      abd.setPrimary(true);
   }
   AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
   if (dependsOn != null) {
      abd.setDependsOn(dependsOn.getStringArray("value"));
   }

   AnnotationAttributes role = attributesFor(metadata, Role.class);
   if (role != null) {
      abd.setRole(role.getNumber("value").intValue());
   }
   AnnotationAttributes description = attributesFor(metadata, Description.class);
   if (description != null) {
      abd.setDescription(description.getString("value"));
   }
}

因为bean 的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺寻中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。

// 获取依赖项
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
        for (String dep : dependsOn) {
                // 判断是否有循环依赖的情况 : A依赖B,B依赖A
                if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                }
                // 注册依赖信息,将依赖信息保存到 dependentBeanMap、dependenciesForBeanMap中
                registerDependentBean(dep, beanName);
                try {
                        // 获取依赖的bean,这一步又回到了最初的getBean
                        getBean(dep);
                }
                catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                }
        }
}

下面我们来看一看 isDependent(beanName, dep) 的处理逻辑

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
        // 是否已经检测过了,上层一直是null
        if (alreadySeen != null && alreadySeen.contains(beanName)) {
                return false;
        }
        // 格式化beanName
        String canonicalName = canonicalName(beanName);
        // 获取 依赖于 beanName 的 bean集合
        Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
        if (dependentBeans == null) {
                return false;
        }
        // 如果 依赖于 beanName中存在 dependentBeanName 则说明存在循环依赖。
        // 代码走到这里说明是beanName 创建过程中要依赖 dependentBeanName。但是dependentBeans.contains(dependentBeanName) = true 则说明dependentBeanName依赖于beanName
        // 造成了 A依赖B,B依赖A的情况
        if (dependentBeans.contains(dependentBeanName)) {
                return true;
        }
        // 递归,确定没有A->B->C-A 这种长链路的循环依赖情况
        for (String transitiveDependency : dependentBeans) {
                if (alreadySeen == null) {
                        alreadySeen = new HashSet<>();
                }
                alreadySeen.add(beanName);
                if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
                        return true;
                }
        }
        return false;
}

注: @DependsOn:注解是在另外一个实例创建之后才创建当前实例,也就是,最终两个实例都会创建,只是顺序不一样 @ConditionalOnBean :注解是只有当另外一个实例存在时,才创建,否则不创建,也就是,最终有可能两个实例都创建了,有可能只创建了一个实例,也有可能一个实例都没创建

3.8 bean创建

上面这么多逻辑,都是准备工作。确定缓存中没有当前bean,并且当前bean的创建合法。准备开始创建。不过这里考虑到不同的 Scope,所以针对不同的Scope进行不同的初始化操作。创建bean 的过程也很复杂。

下面代码就是根据 Singleton、Prototype 或者其他Scope 走不同的流程创建bean。

// Create bean instance.
if (mbd.isSingleton()) {
        // 单例的创建
        sharedInstance = getSingleton(beanName, () -> {
                try {
                        return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                        destroySingleton(beanName);
                        throw ex;
                }
        });
        // 解决FactoryBean的问题
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
        // It's a prototype -> create a new instance.
        // 原型模式的回调
        Object prototypeInstance = null;
        try {
                // 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中
                beforePrototypeCreation(beanName);
                // 直接创建bean
                prototypeInstance = createBean(beanName, mbd, args);
        }
        finally {
                // 移除当前线程正在创建的beanName 从 prototypesCurrentlyInCreation 中
                afterPrototypeCreation(beanName);
        }
        // 解决FactoryBean的问题
        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
        String scopeName = mbd.getScope();
        final 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, () -> {
                // 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中
                        beforePrototypeCreation(beanName);
                        try {
                                // 创建bean
                                return createBean(beanName, mbd, args);
                        }
                        finally {
                                // 移除当前线程正在创建的beanName 从 prototypesCurrentlyInCreation 中
                                afterPrototypeCreation(beanName);
                        }
                });
                //  解决FactoryBean的问题
                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
        }
        catch (IllegalStateException ex) {
                throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
        }
}

关于 bean 创建的过程 getSingleton ,下面进行分析。

3.9 类型转换

到这里整个流程基本就结束了。通常对该方法的调用参数 requiredType 是null,。但某些情况可能会出现返回的bean是个String类型,但是requiredType 传入的却是Integer类型,这时候就会触发这一步的操作,将String类型转换为Integer类型。

if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
        }
        catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                        logger.trace("Failed to convert bean '" + name + "' to required type '" +
                                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
}

4. getSingleton:bean的获取

DefaultSingletonBeanRegistry#getSingleton(java.lang.String, ObjectFactory<?>)这一步创建了bean,我们来分析 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法整个流程。

4.1 获取单例 - getSingleton

如下, 是整个 getSingleton方法的代码,做了一些基本注释

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        // 因为创建过程中需要操作 singletonObjects。所以需要加锁
        synchronized (this.singletonObjects) {
                // 1. 再次尝试获取bean,判断bean是否已经加载。如果加载直接返回。
                Object singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                        // 2. 判断,如果当前beanFactory正在被销毁则直接抛出异常,不允许创建单例bean
                        if (this.singletonsCurrentlyInDestruction) {
                                throw new BeanCreationNotAllowedException(beanName,
                                                "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                                                "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                        }
                        if (logger.isDebugEnabled()) {
                                logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                        }
                        // 3. 做一些bean创建前的准备工作: 记录beanName 正在加载的状态(添加到 singletonsCurrentlyInCreation 缓存中),若bean已经正在加载,则抛出异常。为了解决循环引用的问题
                        beforeSingletonCreation(beanName);
                        boolean newSingleton = false;
                        boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                        if (recordSuppressedExceptions) {
                                this.suppressedExceptions = new LinkedHashSet<>();
                        }
                        try {
                                // 4. 通过回调方式获取bean实例。
                                singletonObject = singletonFactory.getObject();
                                newSingleton = true;
                        }
                        catch (IllegalStateException ex) {
                                // Has the singleton object implicitly appeared in the meantime ->
                                // if yes, proceed with it since the exception indicates that state.
                                singletonObject = this.singletonObjects.get(beanName);
                                if (singletonObject == null) {
                                        throw ex;
                                }
                        }
                        catch (BeanCreationException ex) {
                                if (recordSuppressedExceptions) {
                                        for (Exception suppressedException : this.suppressedExceptions) {
                                                ex.addRelatedCause(suppressedException);
                                        }
                                }
                                throw ex;
                        }
                        finally {
                                if (recordSuppressedExceptions) {
                                        this.suppressedExceptions = null;
                                }
                                // 5. 加载单例后的处理方法调用 : 删除bean正在创建的记录(从 singletonsCurrentlyInCreation  中移除 beanName)
                                afterSingletonCreation(beanName);
                        }
                        if (newSingleton) {
                                // 6. 加入到缓存中,并删除加载bean过程中所记录的各种辅助状态
                                addSingleton(beanName, singletonObject);
                        }
                }
                return singletonObject;
        }
}

...
// 主要还是对几个缓存map的操作
protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
                this.singletonObjects.put(beanName, singletonObject);
                this.singletonFactories.remove(beanName);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
        }
}
...
// 不包含 && 添加失败 :则认为Bean正在创建中,抛出异常
protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
        }
}
...
// 不包含 && 移除失败 :认为Bean 已经创建结束,抛出异常。
protected void afterSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
                throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
}

上面的代码注释也比较清楚,基本流程如下:

  1. this.singletonObjects.get(beanName); :再次尝试从缓存中获取bean,若获取到,则直接返回。
  2. if (this.singletonsCurrentlyInDestruction) :未获取到检测bena是否正在销毁,若是则抛出异常
  3. beforeSingletonCreation 方法中记录bean正在创建的状态将beanName添加到singletonsCurrentlyInCreation集合中)。在循环依赖时可根据此判断。
  4. singletonObject = singletonFactory.getObject(); :调用 ObjectFactory.getObject() 方法来实例化bean
  5. afterSingletonCreation 方法移除bean正在夹杂的状态
  6. addSingleton(beanName, singletonObject); : 对各种缓存状态做处理。

流程图如下所示 :下面的流程图关于 beforeSingletonCreation 和 afterSingletonCreation 的注释写的有些问题,正确的描述如下:

  • inCreationCheckExclusions 不包含 beanName && singletonsCurrentlyInCreation 添加失败 :则认为Bean正在创建中,抛出异常
  • inCreationCheckExclusions 不包含 beanName && singletonsCurrentlyInCreation 移除失败 :认为Bean 已经创建结束,抛出异常。

Spring5源码7-Bean创建及初始化(上)

可以非常直观的看出, getSingleton 方法中的关键逻辑非常简单,bean创建的具体逻辑在 singletonObject = singletonFactory.getObject(); 中,所以下面继续去分析singletonFactory.getObject()中做了什么。

4.2 创建bean - createBean概述

上面可以看到,主要步骤还是在回调的 getObject() 方法中。那么我们来看看在bean加载过程中的FactoryBean做了什么。代码如下:

Spring5源码7-Bean创建及初始化(上)

兜了一大圈关键代码还是在createBean 方法里。接下来,我们就来仔细分析一下 createBean 方法。

AbstractAutowireCapableBeanFactory#createBean 方法代码如下 ,附带部分注释:

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {


        RootBeanDefinition mbdToUse = mbd;


        // 1. 锁定class, 根据mdb和 beanName 解析出来 class
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
                // 2. 验证及准备覆盖的方法
                mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                                beanName, "Validation of method overrides failed", ex);
        }

        try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                // 3. 调用BeanProcessors的方法来替代真正的实例
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                // 如果后处理器真的实现了,则直接返回使用后处理器的bean
                if (bean != null) {
                        return bean;
                }
        }
        catch (Throwable ex) {
                throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                                "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
                // 4.  创建bean 的 真正方法
                Object beanInstance = doCreateBean(beanName, mbdToUse, args);
                if (logger.isTraceEnabled()) {
                        logger.trace("Finished creating instance of bean '" + beanName + "'");
                }
                return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
                throw ex;
        }
        catch (Throwable ex) {
                throw new BeanCreationException(
                                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
}

可以看到,createBean 的整体流程大致如下:

  1. 根据设置的class属性或者根据className来解析Class。
  2. 对override 属性进行标记及验证。
  3. 应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作。
  4. 创建bean。
  5. 返回bean

流程图如下:

Spring5源码7-Bean创建及初始化(上)

上面的逻辑看着似乎不复杂,实际上,真正的逻辑都被封装在了方法中,所以下面需要关注如下的几个方法:

4.2.1 resolveBeanClass

这里不再过多展示代码,这个方法的作用就是根据参数和返回值都能知道: 根据 BeanDefinition和 beanName 解析出 bean 的Class。

Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

4.2.2 prepareMethodOverrides

见名知意: 准备方法重写,这里更多是做一个校验的功能。这个方法主要是针对 lookup-method 和 replaced-method 两个属性的,用来覆盖指定的方法。

mbdToUse.prepareMethodOverrides();

详细代码如下:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   // Check that lookup methods exist and determine their overloaded status.
   // 判断是否有方法需要重写
   if (hasMethodOverrides()) {
      getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
   }
}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
   // 获取对应的类中的对应方法名的个数
   int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
   // 等于0抛出异常。上面已经验证有方法需要覆盖,这里为0肯定错误
   if (count == 0) {
      throw new BeanDefinitionValidationException(
            "Invalid method override: no method with name '" + mo.getMethodName() +
            "' on class [" + getBeanClassName() + "]");
   }
   else if (count == 1) {
      // Mark override as not overloaded, to avoid the overhead of arg type checking.
      // 标记 MethodOverride 暂未被覆盖,避免参数类型检查的开销。
      mo.setOverloaded(false);
   }
}

解释一下上面的逻辑:

  1. 首先会判断是否有方法需要重写,这里的是根据 RootBeanDefinition 中的 methodOverrides 属性来进行判断,为空则表示没有。
  2. 若上述判断有方法需要覆盖,则会调用prepareMethodOverride(MethodOverride mo) 方法。而在 prepareMethodOverride(MethodOverride mo) 方法中会根据 需要覆盖的方法名称 来获取加载类中关于该方法的实现。如果获取不到 count == 0,则直接抛出异常,如果获取到只有一个 count == 1,则记录该方法并未被重载(因为Spring在方法匹配时,如果一个类中存在若干个重载方法,则在函数调用及增强的时候需要根据参数类型进行匹配,来最终确定调用的方法是哪一个,这里直接设置了该方法并未被重载,在后续方法匹配的时候就不需要进行参数匹配验证,直接调用即可)。
  3. 打个比方,比如指定覆盖A类中的 a方法,但是A类中可能存在多个a方法或者不存在a方法,若count == 0不 存在a方法,则谈何覆盖,直接抛出异常,若count ==1 则a方法的实现只有一个,标记该方法并未被重载后续可跳过参数验证的步骤。

4.2.3 resolveBeforeInstantiation

该方法主要是调用 InstantiationAwareBeanPostProcessor 来进行一些处理,这里实际上是给了用户一次代替Spring来创建bean的机会,代码实现上非常简单直接调用的后处理器方法。

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果通过后置处理器创建出来bean,则直接返回创建的bean
if (bean != null) {
        return bean;
}

该方法调用了后处理器的方法:

  • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation : 在bean初始化前调用
  • BeanPostProcessor#postProcessAfterInitialization : 在bean初始化后调用
  • 关于后置处理器部分具体介绍请看Spring5源码5-Bean生命周期后置处理器

详细代码如下:在调用 doCreate 方法创建bean的实例前调用了该方法对 BeanDefinition 中的属性做一些前置处理。

@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        // 如果尚未被解析
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
                // Make sure bean class is actually resolved at this point.
                // 当前类并非合成类 && 存在 BeanPostProcessor (后处理器)
                if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                        // 1. 获取目标类
                        Class<?> targetType = determineTargetType(beanName, mbd);
                        if (targetType != null) {
                                // 2. 实例前的后处理器应用
                                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                                if (bean != null) {
                                        // 3. 实例后的后处理器应用
                                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                                }
                        }
                }
                mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
}

其中 applyBeanPostProcessorsBeforeInstantiationapplyBeanPostProcessorsAfterInitialization 很明显就是调用bean的后置处理器,也就是对后置处理器中的 InstantiationAwareBeanPostProcessor 类型的后处理器进行 postProcessBeforeInstantiation 方法BeanPostProcessor 类型的 postProcessAfterInitialization 方法的调用。

4.2.3.1 determineTargetType(beanName, mbd);

关于 factoryMethodName 值的由来,即如果通过@Bean 注入,则保存期工厂类的方法名称,简单来说就是配置类中对应该bean的注入方法名称。

@Nullable
protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
        // 获取目标类。这里获取的目标类并不一定是真正生成的类,可能是其真正类的父类或者父接口
        Class<?> targetType = mbd.getTargetType();
        if (targetType == null) {
                // 根据mdb 是否存在 factoryMethodName 来确定是直接解析class还是通过 工厂类的方法返回值来获取class
                targetType = (mbd.getFactoryMethodName() != null ?
                                getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
                                resolveBeanClass(mbd, beanName, typesToMatch));
                if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
                        mbd.resolvedTargetType = targetType;
                }
        }
        return targetType;
}

需要注意的是 这里获取的 targetType 类型并不一定是真正生成的bean类型,也可能是实际类型 的父类或者父接口 。因为对于通过 @Bean 注解修饰注入到Spring容器的时候,BeanDefinitionfactoryMethodName 属性值不为空,指向其工厂类的方法名。并且由于多态的特性,其工厂方法引入的类型并不一定是实际类型。这个类型的错误会在 AbstractAutowireCapableBeanFactory#doCreateBean 中纠正过来.

比如 :下面的 demoService()方法实际生成的类型是 DemoServiceImpl。这里返回的类型是DemoService 。那么我们这里获取到的 targetType 就是 DemoService.class。其 BeanDefinition.factoryMethodName = demoService (即 DemoConfig 生成DemoService的方法的名称)

public class DemoConfig {
    @Bean
    public DemoService demoService() {
        return new DemoServiceImpl();
    }
}

4.2.3.2 postProcessBeforeInstantiation

在bean 实例化前调用,也就是将 AbstractBeanDefinition 转换为 BeanWrapper 前的处理。给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法后,bean可能已经不是我们所认为的bean了。或许是一个经过代理的代理bean。可能是通过cglib生成的,也可能是通过其他技术生成的。

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        // 获取所有 BeanPostProcessor 进行遍历
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;				
                        // 调用 postProcessBeforeInstantiation 方法
                        Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                        if (result != null) {
                                return result;
                        }
                }
        }
        return null;
}

4.2.3.3 postProcessAfterInitialization

这里是bean创建后的后置方法调用,逻辑基本类似。不同的是到达这一步时,Bean已经创建成功,并且注入属性也进行了赋值。

需要注意,如果bean交由Spring来创建,那么Spring会将需要的属性注入到bean中,如果是自己代理生成(比如 通过 postProcessBeforeInstantiation 方法生成),那么需要自己解决bean的属性注入问题。

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                        return result;
                }
                result = current;
        }
        return result;
}

4.3 创建bean - doCreateBean

代码执行到这里,可以确定第三步中并没有返回一个非空的bean(BeanPostProcessor 并没有代理生成一个bean)。所以Spring开始自己着手创建bean。do开头的方法才是真正做事情的,所以这里才是真正创建bean的地方。

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

doCreateBean 代码如下,带有详细注释:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   // 是否单例
   if (mbd.isSingleton()) {
      // 单例情况下清除缓存。这里保存的是 FactoryBean 和 BeanWrapper 的映射关系。
      // factoryBeanInstanceCache 是在创建其他bean的时候缓存了一下 FactoryBean 。
      // 至于单例模式下移除而不是获取,因为单例只需要创建一次 ? 尚未理解。
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   // 如果没有缓存,则重新创建
   if (instanceWrapper == null) {
      // todo 创建Bean实例 ,默认使用无参构造器创建的对象,组件的实例就创建了
      // 1. 根据指定的bean使用对应的策略创建新的实例。如:工厂方法、构造函数自动注入,简单初始化
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   // 获取bean实例
   Object bean = instanceWrapper.getWrappedInstance();
   // 获取bean类型
   Class<?> beanType = instanceWrapper.getWrappedClass();
   // 将目标类型替换成实际生成的类型.纠正了上面说到类型错误(如果存在)
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   // MergedBeanDefinitionPostProcessor 后置处理器再来修改下BeanDefinition 信息
   // 2. 调用  MergedBeanDefinitionPostProcessor 后处理器
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            // todo 执行MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()方法
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   // 提前暴露 单实例bean 专门来解决循坏引用的问题
   // 3. 判断是否需要提早曝光 : 单例 & 允许循环依赖 & 当前bean已经正在创建中
   // 由于当前bean已经在创建中,本次创建必然是循环引用造成的,所以这里判断是否可以需要提前曝光
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      // 添加
      // 三级缓存中Bean也会被后置处理来增强
      // 4. 为避免后期循环依赖,在bean初始化完成前将创建实例的ObjectFactory 加入工程  -- 解决循环依赖
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      // todo 对象中的每个属性赋值
      //  5. 对bean进行属性填充,将各个属性值注入,其中如果存在依赖于其他bean的属性,则会递归初始依赖bean
      populateBean(beanName, mbd, instanceWrapper);
      // todo 初始化Bean
      // 调用初始化方法,比如 init-method
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }
   // 早期单实例暴露
   // 6. 进行循环依赖检查
   if (earlySingletonExposure) {
      // 检查早期缓存中是否存在这个组件
      // earlySingletonReference  只有在检测到有循环依赖的情况下才会不为空
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         // 如果 exposedObject没有在初始化方法中被改变,也就是没有被增强
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               // 检测依赖
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            // 因为bean创建后其所依赖的bean一定是已经创建了的。
            // actualDependentBeans不为空说明当前 bean创建后其依赖的bena却没有全部创建完,也就说说存在循环依赖。
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   try {
      // 7.根据Scopse 注册bean
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

可以看到大致逻辑如下:

  1. createBeanInstance(beanName, mbd, args) :实例化bean,将BeanDefinition转换为BeanWrapper
  2. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); : MergedBeanDefinitionPostProcessor 后处理器的应用。bean合并后的处理,比如 @Autowired、@Value注解正是通过 AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition 此方法实现的预解析。
  3. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); : 关于循环依赖的处理,添加 ObjectFactory到singletonFactories缓存中,同时这里给了用户一个机会通过调用 SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference 方法来由用户生成暴露的实例
  4. populateBean(beanName, mbd, instanceWrapper); :对创建的bean内部的一些属性进行填充注入
  5. initializeBean(beanName, exposedObject, mbd); : 初始化bean的一些属性,如Aware 接口的实现, init-method属性等
  6. 循环依赖检查。和第四步不同的是,这里了是判断是否无法解决循环依赖,否则抛出异常。
  7. registerDisposableBeanIfNecessary(beanName, bean, mbd); : 注册DisposableBean
  8. 完成创建并返回。

doCreatebean 方法的代码量非常大,这里由于篇幅问题,需要新开篇分析,所以本文中挑选几个简单的方法分析,复杂的方法新开篇分析。

4.3.1 createBeanInstance

见名知意 : 该方法完成了bean的实例创建。

instanceWrapper = createBeanInstance(beanName, mbd, args);

大概逻辑可以概括为:

  • 如果存在工厂方法则使用工厂方法进行初始化
  • 若类有多个构造函数,则根据参数锁定构造函数并初始化
  • 如果即不存在工厂方法也不存在带参构造函数,则使用默认的构造函数进行bean的实例化。

这里详细见第5小节分析。

4.3.2 applyMergedBeanDefinitionPostProcessors

这种方法命名的也见得多了,见名知意: 该方法完成了 MergedBeanDefinitionPostProcessors 后处理器的功能。主要是 bean合并后的处理。在 AutowiredAnnotationBeanPostProcessor对postProcessMergedBeanDefinition方法的实现中,就对@Autowired、@Value 等注解进行了一系列的预处理,这里我们并不需要太过在意。

关于 AutowiredAnnotationBeanPostProcessor 的内容,后面单独开一篇来分析。

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

详细代码如下,不再具体分析

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof MergedBeanDefinitionPostProcessor) {
                        MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                        bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
                }
        }
}

4.3.3 addSingletonFactory

这一部分的逻辑就是为了解决循环依赖的问题,将未创建完成的当前bean,通过ObjectFactory进行一个包装,提前暴露给其他bean。

我们实际的分析是一部分代码块如下:

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                        isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                                "' to allow for resolving potential circular references");
        }
        // 这里为了避免后期的循环依赖,在bean初始化前将创建实例的ObjectFactory加入工厂中。
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

首先我们需要分析出 earlySingletonExposure 为true的条件:

  • bean是单例
  • 允许循环依赖
  • 当前bean正在创建中 : singletonsCurrentlyInCreation 包含当前bean。在Spring 中 有专门的属性记录 bean的加载状态 – DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation。在bean创建前会将bean添加,bean创建结束后将bean移除。这一点我们在前篇有过提及。

满足上述三个条件后,则会 调用 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 方法。这个方法作用是将正在创建的bean缓存起来,主要目的还是用来解决循环依赖的问题。

详细代码如下:

// 对一系列缓存map 做处理。在 singletonFactories 中保存 ObjectFactory 类型,进行提前暴露
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
                // 如果singletonObjects不存在(bean未创建成功)
                if (!this.singletonObjects.containsKey(beanName)) {
                        this.singletonFactories.put(beanName, singletonFactory);
                        this.earlySingletonObjects.remove(beanName);
                        this.registeredSingletons.add(beanName);
                }
        }
}

...
// 给调用者一次机会,主要就是调用了SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference 方法。将getEarlyBeanReference  方法的返回值作为提前暴露的对象。
// 我们可以通过实现 getEarlyBeanReference  方法来替代Spring提前暴露的对象
// Aop 就是在这里将 Advice 动态织入bean中,若没有bean则直接返回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;
}

该方法中 getEarlyBeanReference 调用了后处理器的方法,可用于用户自己扩展替换Spring生成的提前暴露的对象 :

  • SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference (Object bean, String beanName);

4.3.4 populateBean

见名知意,下面这个方法是用来属性注入的。 populateBean 方法则是对bean 属性的注入,上面的 createBeanInstance 方法创建了 bean,但是其内部属性并没有注入,比如通过 @Autowired 注解注入的变量属性,此时还为null,需要对这种属性进行注入,这一步就是完成这种功能。

	populateBean(beanName, mbd, instanceWrapper);

在这里方法里按照如下顺序调用了后处理器

  • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation : 返回true 才会调用下面两个方法
    • InstantiationAwareBeanPostProcessor.postProcessProperties : 进行属性的注入。
    • InstantiationAwareBeanPostProcessor.postProcessPropertyValues : 已过时 详细的代码分析后面分析。

4.3.5 initializeBean

到达这一步,其实bean已经创建结束了,这一步是完成最后的功能,提供一些功能的实现,如Aware 接口的实现, init-method、InitializingBean属性等。

	exposedObject = initializeBean(beanName, exposedObject, mbd);

详情后面分析

4.3.6 循环依赖检查

Spring 循环依赖的解决仅对单例且非构造函数构造的形式有效,对于原型模式的bean,Spring直接抛出异常,在这个步骤中会检测已经加载的bean 是否已经出现了循环依赖,并判断是否需要抛出异常。

// earlySingletonExposure 为true 说明要校验循环依赖的问题
if (earlySingletonExposure) {
        // 调用了 getSingleton 方法获取缓存中的对象,这里注意传递的false。
        Object earlySingletonReference = getSingleton(beanName, false);
        // 如果 earlySingletonReference  不为空,则说明存在循环依赖
        if (earlySingletonReference != null) {
                // 如果缓存的对象 exposedObject == bean,直接赋值之前暴露出来的bean
                // 这里
                if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                }
                // allowRawInjectionDespiteWrapping 默认false && beanName 被其他bean依赖
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                        // 获取依赖于 当前bean的 beanName
                        String[] dependentBeans = getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                        for (String dependentBean : dependentBeans) {
                                // 
                                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                        actualDependentBeans.add(dependentBean);
                                }
                        }
                        // 如果 actualDependentBeans 不为空,则抛出循环依赖的异常
                        if (!actualDependentBeans.isEmpty()) {
                                throw new BeanCurrentlyInCreationException(beanName,
                                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                                "] in its raw version as part of a circular reference, but has eventually been " +
                                                "wrapped. This means that said other beans do not use the final version of the " +
                                                "bean. This is often the result of over-eager type matching - consider using " +
                                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                        }
                }
        }
}

...
// 上面调用的 getSingleton 方法。可以知道这里传递的 allowEarlyReference 为false。
// 因为当前bean在进行循环创建的时候,就已经将 bean缓存到 earlySingletonObjects 中了
// DCL
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   // 检查单例缓存池 中有没有
   Object singletonObject = this.singletonObjects.get(beanName);  // 以及缓存
   // 如果当前bean正在创建中,而且缓存中没有则继续
   // 单例缓存中没有对象 && 当前单例bean正在创建中,这是为了解决循环依赖的问题
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 如果此时bean正在加载(bean 在 earlySingletonObjects 中),则直接将singletonObject 返回。
      singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
      // allowEarlyReference = true 才会允许循环依赖
      if (singletonObject == null && allowEarlyReference) {
         // 如果单例缓存中不存在该bean,则加锁进行接下来的处理
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  // 当某些方法需要提前初始化的时候则会调用addSingletonFactory
                  // 将对应的ObjectFactory初始化策略存储在singletonFactories中
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);  // 三级缓存
                  if (singletonFactory != null) {
                     // 调用预先设定的getObject方法
                     singletonObject = singletonFactory.getObject();
                     // 记录在缓存中,earlySingletonObjects 和 singletonFactories互斥
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}
...
// 删除给定bean名称的单例实例(如果有的话),但前提是该类型仅用于类型检查以外的用途。
protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
        if (!this.alreadyCreated.contains(beanName)) {
                removeSingleton(beanName);
                return true;
        }
        else {
                return false;
        }
}
...
protected void removeSingleton(String beanName) {
        synchronized (getSingletonMutex()) {
                super.removeSingleton(beanName);
                this.factoryBeanObjectCache.remove(beanName);
        }
}
...
// super.removeSingleton(beanName); 如下
protected void removeSingleton(String beanName) {
        synchronized (this.singletonObjects) {
                this.singletonObjects.remove(beanName);
                this.singletonFactories.remove(beanName);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.remove(beanName);
        }
}

关于这一段的逻辑参考 : blog.csdn.net/qq_18297675…

整个逻辑如下:

  1. getSingleton(beanName, false); : 从缓存中获取缓存对象,这传递的false, 直接从 earlySingletonObjects 中获取循环依赖的对象 earlySingletonReference
  2. 如果 earlySingletonReference == bean ,说明bean没有被修改,直接赋值即可。
  3. 如果 earlySingletonReference != bean ,那么说明 在 下面的代码中,bean被修改了
    populateBean(beanName, mbd, instanceWrapper);
    exposedObject = initializeBean(beanName, exposedObject, mbd);

此时需获取依赖于当前bean的 dependentBeans。如果dependentBeans 中有已经创建好的,那么则抛出异常

4.3.7 registerDisposableBeanIfNecessary

这一步的目的是实现 destory-method 属性,如果bean配置了该属性,则需要注册以便在销毁时调用。

详细代码如下:

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
        AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
        if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
                if (mbd.isSingleton()) {
                        // Register a DisposableBean implementation that performs all destruction
                        // work for the given bean: DestructionAwareBeanPostProcessors,
                        // DisposableBean interface, custom destroy method.
                        // 单例模式下注册需要销毁的bean,此方法会处理实现DisposableBean的bean
                        // 并且对所有的bean使用 DestructionAwareBeanPostProcessor 处理 DisposableBean DestructionAwareBeanPostProcessor
                        registerDisposableBean(beanName,
                                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
                }
                else {
                        // A bean with a custom scope...
                        // 自定义 scope 的处理
                        Scope scope = this.scopes.get(mbd.getScope());
                        if (scope == null) {
                                throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
                        }
                        scope.registerDestructionCallback(beanName,
                                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
                }
        }
}

篇幅有限,剩下的几个核心方法,下一篇文章阐述,敬请期待。

参考文章

Spring5源码注释github地址 Spring源码深度解析(第2版) spring源码解析 Spring源码深度解析笔记 Spring注解与源码分析 Spring注解驱动开发B站教程