Spring源码——bean的加载

版权声明:本文为博主原创文章,转载注明出处即可。 https://blog.csdn.net/bskfnvjtlyzmv867/article/details/82859993

前言

内容主要参考自《Spring源码深度解析》一书,算是读书笔记或是原书的补充。进入正文后可能会引来各种不适,毕竟阅读源码是件极其痛苦的事情。

本文主要涉及书中第五章的部分,依照书中内容以及个人理解对Spring进行了注释,详见Github仓库:https://github.com/MrSorrow/spring-framework

在前几篇文章中,我们已经完成了将XML配置文件的信息转换为 BeanDefinition 的形式,将所有的 bean 从配置文件加载到内存中,接下来便是如何来 使用加载 这些 beanbean 加载的功能实现远比 bean 的解析要复杂的多。

I. 加载bean总览

我们在 spring-mytest 模块中,获取实例对象通过如下代码:

MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");

Spring通过调用 BeanFactorygetBean() 方法来加载 bean,我们进入 AbstractBeanFactory 来看一下源码:

/**
 * 根据名称获取bean实例
 * @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);
}

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

    // 提取对应的bean名称
    final String beanName = transformedBeanName(name);
    Object bean;

    // 检查缓存中或者实例工厂中是否有对应的实例
    // 为什么会首先使用这段代码?
    // 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
    // Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
    // 也就是将ObjectFactory加入到缓存中,一旦下个bean创建的时候需要依赖上个bean则直接使用ObjectFactory

    // 直接尝试从缓存中获取或者singletonFactories中的ObjectFactory中获取
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                             "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    // 缓存中取不到
    else {
        // 只有在单例情况下才会尝试解决循环依赖;
        // 原型模式情况下,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为
        // 对于B的创建再次返回到创建A,造成循环依赖,也就是下面的情况。对于“prototype”作用域Bean,Spring容器无法完成依赖注入,
        // 因为“prototype”作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean。
        // 参考:http://www.cnblogs.com/bhlsheji/p/5208076.html
        // isPrototypeCurrentlyInCreation(beanName)为true
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();

        // 如果beanDefinitionMap中也就是已经加载的类中不包括beanName则尝试从parentBeanFactory中检测
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            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.
                // 递归到BeanFactory中寻找
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        // 如果不仅仅是做类型检查则是创建bean,这里要进行记录
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            // 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            // 若存在依赖则需要递归实例化依赖的bean
            if (dependsOn != null) {
                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 {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            // 实例化依赖的bean后便可以实例化mbd本身了
            // singleton模式的创建
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 核心所在
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // Explicitly remove instance from singleton cache: It might have been put there
                        // eagerly by the creation process, to allow for circular reference resolution.
                        // Also remove any beans that received a temporary reference to the bean.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

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

            else {
                // 指定的scope上实例化bean
                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, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    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);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

这段代码可以说是巨长了,其中的过程相当复杂,同时可以根据本文的长度可见一斑。通过上面的注释,大致了解到Spring加载 bean 的过程如下:

① 转换对应的beanName

转换对应的 beanName 是根据 getBean(String name) 方法传入的 name 参数进行的,传入的 name 并不一定是 beanName,可能是别名,也可能是 FactoryBean 。至于什么是 FactoryBean ,后面会提及。由于 name 的多种可能,Spring会进行对应的转换。

  • 去除 FactoryBean 的修饰符,一般就是去除 name 参数的 & 前缀,从代码上能够清晰的看出;
  • 取指定的 alias 所表示的最终 beanName,例如别名 A 指向别名 B,别名 B 指向名称为 Cbean,则最后返回 C
/**
 * Return the bean name, stripping out the factory dereference prefix if necessary,
 * and resolving aliases to canonical names.
 * @param name the user-specified name
 * @return the transformed bean name
 */
protected String transformedBeanName(String name) {
   return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

去除 FactoryBean 的修饰符:

/**
 * 去掉xml中bean标签name属性的前缀&
 * Return the actual bean name, stripping out the factory dereference
 * prefix (if any, also stripping repeated factory prefixes if found).
 * @param name the name of the bean
 * @return the transformed name
 * @see BeanFactory#FACTORY_BEAN_PREFIX
 */
public static String transformedBeanName(String name) {
   Assert.notNull(name, "'name' must not be null");
   String beanName = name;
   while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
      beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
   }
   return beanName;
}

取指定的 alias 所表示的最终 beanName

/**
 * Determine the raw name, resolving aliases to canonical names.
 * @param name the user-specified name
 * @return the transformed name
 */
public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

② 尝试从缓存中加载单例

单例在Spring中的同一个容器内只会被创建一次,后续再获取 bean,则直接从单例缓存中获取了。当然代码实现上首先进行尝试从缓存中进行加载,如果不成功再尝试从 singletonFactories 中加载,最后都不行才判断是没有创建过所以新建并放入缓存。之所以需要从 singletonFactories 中加载,因为在创建单例 bean 的时候会存在依赖注入 的情况,而在创建依赖 bean 的时候,为了避免循环依赖,Spring中创建 bean 的原则是不等 bean 创建完成就会提前将创建 beanObjectFactory 曝光加入到缓存中,一旦下一个 bean 创建的时候需要依赖该 bean 时则可以直接使用 ObjectFactory 作为依赖进行注入。对于循环依赖,后面会具体再说。

③ bean的实例化

如果从缓存中得到了 bean 的原始状态,则需要对 bean 进行实例化。缓存中记录的只是最原始的 bean 状态,并不是我们最终想要的 bean。例如:假如我们需要对工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但我们真正需要的是工厂 bean 中定义的 factory-method 方法中返回的 bean,而 getObjectForBeanInstance(sharedInstance, name, beanName, null) 就是完成这项工作。对于原始状态的 bean 进行实例化,后面也会具体说。

④ 原型模式(prototype)的依赖检查

Spring能够尝试解决的循环依赖问题只有单例模式下,对于原型模式的循环依赖问题Spring是没有方法解决的。因为在原型模式(prototype)下,如果 A 依赖 BB 同时又依赖 A,那么就会出现创建 A 时因为创建依赖 B 而又要创建 A ,因为是多例的,所以会一直循环创建。Spring对于原型模式下的循环依赖会进行检测,检测代码为 isPrototypeCurrentlyInCreation(beanName) ,如果为 true,则会抛出异常。

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

⑤ 检测parentBeanFactory

代码上的逻辑可以看出,如果从缓存中没有取到,那么直接转到父类工厂上去加载了。Why?代码中的判断逻辑是:if (parentBeanFactory != null && !containsBeanDefinition(beanName)) ,前半部分还好,parentBeanFactory 不能为空,后半部分 !containsBeanDefinition(beanName) 意思如果当前的 beanDefinitionMap (XML配置文件)中没有 beanName 对应的配置,就只能到 parentBeanFactory 中去尝试下,再递归的调用 getBean() 方法了。

// 如果beanDefinitionMap中也就是已经加载的类中不包括beanName则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   // Not found -> check parent.
   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.
      // 递归到BeanFactory中寻找
      return (T) parentBeanFactory.getBean(nameToLookup, args);
   }
   else {
      // No args -> delegate to standard getBean method.
      return parentBeanFactory.getBean(nameToLookup, requiredType);
   }
}

⑥ GenericBeanDefinition转为RootBeanDefinition

如果从缓存中获取不到,同时当前的 beanDefinitionMap 中存在对应 beanName 的配置,我们就可以依据包含有XML配置文件信息的 beanDefinition 进行创建 bean 了。通过前面几篇文章,我们知道从XML配置文件中读取到的 bean 信息是利用 GenericBeanDefinition 存储的,但是后面Spring对所有 bean 的后续处理都是针对于 RootBeanDefinition 的,所以需要进行转换,转换的同时如果父类 bean 不为空,则会一并合并父类的属性

// 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

⑦ 寻找依赖

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

// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
// 若存在依赖则需要递归实例化依赖的bean
if (dependsOn != null) {
   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 {
         getBean(dep);
      }
      catch (NoSuchBeanDefinitionException ex) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
      }
   }
}

⑧ 依据scope创建bean

Spring存在不同的 scope,其中默认的是 singleton,但是还有其他的配置像 prototyperequest 等。(关于Spring的几种 scope 介绍,参考这篇文章。)在这一步中,Spring会根据配置进行采取对应的初始化策略。代码缩略如下:

if (mbd.isSingleton()) {
   .....
}

else if (mbd.isPrototype()) {
   // It's a prototype -> create a new instance.
   // prototype原型模式的创建(new)
   .....
}

else {
   // 指定的scope上实例化bean
   .....
}

⑨ 类型转换

根据 scope 创建完 bean 成功后,一般可以直接返回即可。但当传入 doGetBean 方法中的 requireType 参数不为空时,意味着我们对最后返回的 bean 有着类型上的要求。Spring一般通过类型转换器将第⑧步创建完成的 bean 转换为 requireType 指定的类型。Spring自身提供了一些转换器,用户也可以自己扩展转换器来满足需求。

// 检查需要的类型是否符合bean的实际类型
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.isDebugEnabled()) {
         logger.debug("Failed to convert bean '" + name + "' to required type '" +
               ClassUtils.getQualifiedName(requiredType) + "'", ex);
      }
      throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
   }
}
return (T) bean;

经过以上的九个步骤,bean 就算创建完成了,整个流程如下图所示。其中第八步最为关键——针对不同的 scope 进行 bean 的创建。

bean的获取过程

这里再附一张其他文章中的流程图:

bean加载流程

在真正开始分析流程前,我们先来做些知识准备工作…

II. FactoryBean的使用

一般情况下,Spring通过反射机制来实例化 bean。在某些情况下,实例化一个 bean 的过程较为复杂,因此配置文件中为该 bean 需要编写大量配置信息,灵活性受限。所以,Spring提供了一个 org.springframework.beans.factory.FactoryBean 的工厂类接口,用户可以实现该接口通过编码的方式定制实例化 bean 的逻辑。简单点,就是配置文件配置自定义的 FactoryBean 接口实现类,但真正实例化出的还是我们需要的对象,只不过繁琐的实例化流程交给 FactoryBean 和Spring商量了。

FactoryBean接口

Spring自身就定义了 70 多种 FactoryBean 的实现,他们隐藏了实例化一些复杂 bean 的细节,给上层应用带来便利。 FactoryBean 接口的定义从 3.0 开始支持泛型:

public interface FactoryBean<T> {
   @Nullable
   T getObject() throws Exception;

   @Nullable
   Class<?> getObjectType();

   default boolean isSingleton() {
      return true;
   }
}

接口中定义了三个方法:

  • T getObject(): 返回由 FactoryBean 创建的 bean 实例。如果 isSingleton() 返回 true,则该实例会放到Spring容器中单例缓存池中;
  • boolean isSingleton(): 返回 bean 的作用域是否是单例模式,默认为 true
  • Class<?> getObjectType(): 返回 FactoryBean 创建的 bean 的类型。

使用示例

当XML配置文件中 <bean>class 属性配置的实现类是 FactoryBean 接口实现类时,通过 T getObject() 方法返回的不是 FactoryBean 本身,而是 FactoryBeanT getObject() 方法返回的对象。

例如,我们定义一个 Car 实体类,需要在Spring中创建 bean,那么需要指定一些 <property> 配置才行。

/**
 * @description: 汽车实体类
 * @author: guoping wang
 * @date: 2018/9/5 10:43
 * @project: spring
 */
public class Car {

   private int maxSpeed;
   private String brand;
   private double price;

   /** setter and getter */
}

使用 FactoryBean 的方式就可以灵活许多,但我们需要自定义 FactoryBean 的实现类:

import org.springframework.beans.factory.FactoryBean;

/**
 * @description: 实现FactoryBean接口创建Car对象
 */
public class CarFactoryBean implements FactoryBean<Car> {

   private String carInfo;

   public String getCarInfo() {
      return carInfo;
   }

   public void setCarInfo(String carInfo) {
      this.carInfo = carInfo;
   }

   @Override
   public Car getObject() throws Exception {
      Car car = new Car();
      String[] splitInfo = carInfo.split(",");
      car.setBrand(splitInfo[0]);
      car.setMaxSpeed(Integer.valueOf(splitInfo[1]));
      car.setPrice(Double.valueOf(splitInfo[2]));
      return car;
   }

   @Override
   public Class<Car> getObjectType() {
      return Car.class;
   }

   @Override
   public boolean isSingleton() {
      return false;
   }
}

最重要的其实就是 T getObject() 方法的重写,其中包含着 Car 实例对象的创建逻辑、属性如何填充等。有了 CarFactoryBean ,在配置文件中我们可以很简洁的定义。

<bean id="testCarFactoryBean" class="guo.ping.ioc.loadbean.CarFactoryBean">
   <property name="carInfo" value="超跑,400,200000" />
</bean>

当Spring通过反射发现 guo.ping.ioc.loadbean.CarFactoryBean 实现了 FactoryBean 接口时,Spring容器会自动调用 CarFactoryBeanCar getObject() 方法返回一个 Car 实例对象。当然,如果你本身只想返回 CarFactoryBean 的实例,那么在使用 getBean(beanName) 方法时在 beanName 前显式的加上 “&” 前缀,例如 getBean("&car")

CarFactoryBean carFactoryBean = (CarFactoryBean) beanFactory.getBean("&testCarFactoryBean");

III. 缓存中获取单例bean

下面我们就正式的开始分析 bean 加载的九大步骤。第一步没什么太多需要再说的了,就是对 name 参数的处理,转换对应的 beanName。相信通过第二部分 FactoryBean 的介绍,更应该了解到去除 FactoryBean 的修饰符含义了。

单例在Spring的同一个容器内只会被创建一次,后续再获取 bean 直接从单例缓存中获取。当然这里也只是尝试加载,首先尝试从 缓存 中加载,然后再次尝试从 singletonFactory 加载。因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring创建 bean 的原则是不等 bean 创建完成就会将创建 beanObjectFactory 提早曝光加入到缓存中,一旦下一个 bean 创建时需要依赖上个 bean,则直接使用ObjectFactory 。我们进入 getSingleton(beanName) 方法体中研究一下:

/**
 * 尝试从缓存中加载bean,然后再尝试从singletonFactories中加载
 * @param beanName the name of the bean to look for
 * @return
 */
@Override
@Nullable
public Object getSingleton(String beanName) {
   // 参数true设置标识允许早期依赖
   return getSingleton(beanName, true);
}

/**
 * 首先尝试从缓存singletonObjects获取实例,如果获取不到再从earlySingletonObjects获取
 * 如果还是获取不到,再从singletonFactories中获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject方法
 * 来创建bean,并放到earlySingletonObjects,并从singletonFactories移除掉这个ObjectFactory
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // 检查缓存中是否存在实例
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 如果缓存中不存在,则锁定全局变量并进行处理
      synchronized (this.singletonObjects) {
         // 如果此bean正在加载则不处理
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
            // 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               // 如果singletonFactory中存在,调用预先设定的getObject方法
               singletonObject = singletonFactory.getObject();
               // 记录在缓存中,earlySingletonObjects和singletonFactories互斥
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return singletonObject;
}

根据注释,我们梳理一下获取缓存 bean 代码的主要逻辑。方法先尝试从 singletonObjects 里面去获取实例,如果获取到,OK,直接返回!如果获取不到,再尝试从 earlySingletonObjects 里面获取,如果获取到,OK,直接返回。那么如果还获取不到,再尝试从 singletonFactories 里面获取 beanName 对应的 ObjectFactory。然后再调用这个 ObjectFactorygetObject() 方法创建 bean,并放到 earlySingletonObjects 里面去,并且从 singletonFactories 里面 remove 掉这个 ObjectFactory,而对于后续所有的内存操作都只为了循环依赖检测时候使用,即 allowEarlyReferencetrue 的时候才会使用。关于循环依赖、 ObjectFactory 后面还会单独着重介绍。

在从缓存中获取未果转向从 earlySingletonObjects 里面获取时,还要判断单例对象是否正在被创建 isSingletonCurrentlyInCreation(beanName) 。只有该 bean 正在被创建 earlySingletonObjectssingletonFactories 里面才可能有。

/**
 * Return whether the specified singleton bean is currently in creation
 * (within the entire factory).
 * @param beanName the name of the bean
 */
public boolean isSingletonCurrentlyInCreation(String beanName) {
   return this.singletonsCurrentlyInCreation.contains(beanName);
}

代码中涉及到很多个存储 bean 的不同 map 集合。我们来罗列一下:

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

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

/** 也是保存BeanName和创建bean实例之间的关系,与singletonObjects不同之处在于,当一个单例bean被放在里面后,
 * 那么bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来循环检测引用
 * Cache of early singleton objects: bean name to bean instance.
 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

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

IV. 从工厂bean的实例中获取对象

在整个 getBean() 方法中,getObjectForBeanInstance(sharedInstance, name, beanName, null) 是一个高频率使用的方法。从上一步的缓存中获取了单例 bean 以及根据不同的 scope 策略加载 bean 都使用了该方法。总之,我们得到 bean 的实例后,要做的第一步就是调用这个方法来检测一下正确性,其实就是检测获得 bean 是不是 FactoryBean 类型的 bean。如果是,那么需要调用该 bean 对应的 FactoryBean 实例中的 getObject() 作为返回值。

无论是从缓存中获取到的 bean 还是通过不同的 scope 策略加载的 bean 都只是最原始的 bean 状态,并不一定是我们最终想要的 bean。举个例子,假如我们需要对工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但我们真正想要的是工厂 bean 中定义的 factory-method 方法中返回的 bean,而getObjectForBeanInstance 方法就是完成这个。

/**
 * 如果从缓存中获取到的bean还是通过不同的scope策略加载到的bean都只是最原始的bean状态
 * 并不一定是我们最终想要的bean。
 * 比如,假如我们需要对工厂bean进行处理,那么之前得到的其实是工厂bean的初始状态,但我们真正需要的是
 * 工厂bean中定义的factory-method方法返回的bean,而getObjectForBeanInstance方法就是完成这个工作的。
 */
protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   // 如果指定的name是工厂相关(是否以&为前缀)
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      // 如果beanInstance是null,则直接返回
      if (beanInstance instanceof NullBean) {
         return beanInstance;
      }
      // 如果指定的name是工厂相关且beanInstance不是FactoryBean类型,则验证不通过
      if (!(beanInstance instanceof FactoryBean)) {
         throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
      }
   }

   // 现在我们有了bean的实例,这个实例可能会是正常的bean或者factoryBean
   // 如果是FactoryBean我们使用它创建实例,但是如果用户想要直接获取工厂实例而不是工厂的getObject方法对应的实例,那么传入的name应该加入&
   if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) 	 {
      return beanInstance;
   }

   // 加载FactoryBean
   Object object = null;
   if (mbd == null) {
      // 尝试从缓存中加载bean,如果缓存中已经存在 beanName 对应的工厂 bean 生成的对象则直接返回
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {
      // 到这里已经明确知道beanInstance一定是FactoryBean类型
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      // containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测是否定义beanName
      if (mbd == null && containsBeanDefinition(beanName)) {
         // 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性
         mbd = getMergedLocalBeanDefinition(beanName);
      }
      // 是否是用户定义的而不是应用程序本身定义的
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      // getObjectFromFactoryBean是本方法的核心
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}

我们详细分析下代码会发现此方法中没有重要信息,大多都是一些辅助功能性的检查判断,而真正的核心功能是在 getObjectFromFactoryBean(factory, beanName, !synthetic) 方法中实现的。不过可以看出,之前第二部分的 FactoryBean 使用相关功能的处理逻辑就是在这里实现的。总的来说,getObjectForBeanInstance 中做了如下几件事情:

  • beanInstance 进行 FactoryBean 正确性的校验;
  • 对非 FactoryBean 类型或者本身就需要返回 FactoryBean 类型对象的 beanInstance 不作处理;
  • 如果缓存中已经存在 beanName 对应的工厂 bean 生成的对象则直接返回;
  • 如果缓存没有,则对 beanInstance 进行强转为 FactoryBean 类型,将从 Factory 中解析获取 bean 的工作委托给 getObjectFromFactoryBean(factory, beanName, !synthetic) 方法。

其中,在直接创建之前会尝试获取缓存,通过 getCachedObjectForFactoryBean(beanName) 方法获取:

/**
 * Obtain an object to expose from the given FactoryBean, if available
 * in cached form. Quick check for minimal synchronization.
 * @param beanName the name of the bean
 * @return the object obtained from the FactoryBean,
 * or {@code null} if not available
 */
@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
   return this.factoryBeanObjectCache.get(beanName);
}

我们继续查看 getObjectFromFactoryBean(factory, beanName, !synthetic)

/**
 * 从FactoryBean获取对象
 * Obtain an object to expose from the given FactoryBean.
 * @param factory the FactoryBean instance
 * @param beanName the name of the bean
 * @param shouldPostProcess whether the bean is subject to post-processing
 * @return the object obtained from the FactoryBean
 * @throws BeanCreationException if FactoryBean object creation failed
 * @see org.springframework.beans.factory.FactoryBean#getObject()
 */
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   // factory是单例的同时,factory还得已经被实例化
   if (factory.isSingleton() && containsSingleton(beanName)) {
      synchronized (getSingletonMutex()) {
         // 再次尝试从缓存中获取bean
         Object object = this.factoryBeanObjectCache.get(beanName);
         if (object == null) {
            // 委托doGetObjectFromFactoryBean方法产生bean
            object = doGetObjectFromFactoryBean(factory, beanName);
            // Only post-process and store if not put there already during getObject() call above
            // (e.g. because of circular reference processing triggered by custom getBean calls)
            // 再次判断缓存中是否有
            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
            if (alreadyThere != null) {
               object = alreadyThere;
            }
            else {
               if (shouldPostProcess) {
                  if (isSingletonCurrentlyInCreation(beanName)) {
                     // Temporarily return non-post-processed object, not storing it yet..
                     return object;
                  }
                  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 {
                     afterSingletonCreation(beanName);
                  }
               }
               // 单例模式下:已经加载的bean要记录下来,便于下次复用
               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;
   }
}

如果返回的 bean 是单例的,就必须保证全局唯一,同时不可重复创建,可以使用缓存来提高性能,也就是说加载过就记录下来以便于下次复用。如果返回的 bean 不是单例的,则直接创建 bean

Spring是怎么进行保证单例模式下 bean 的全局唯一呢?在代码 16 和 19 行,分别在创建 bean 前后进行双重判断缓存中是否能通过 beanName 获取到实例。这里的缓存就是 this.factoryBeanObjectCache 这个 ConcurrentHashMap 。该方法在创建完成 bean 后,最后会将其添加至缓存。

我们大致讲了 getObjectFromFactoryBean() 方法的前面和末尾的流程,其中创建 bean 的工作实际交给了 doGetObjectFromFactoryBean(factory, beanName) 方法去完成。

/**
 * Obtain an object to expose from the given FactoryBean.
 * @param factory the FactoryBean instance
 * @param beanName the name of the bean
 * @return the object obtained from the FactoryBean
 * @throws BeanCreationException if FactoryBean object creation failed
 * @see org.springframework.beans.factory.FactoryBean#getObject()
 */
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
      throws BeanCreationException {

   Object object;
   try {
      // 需要权限认证
      if (System.getSecurityManager() != null) {
         AccessControlContext acc = getAccessControlContext();
         try {
            object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
         }
         catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }
      else {
         // 获取bean
         object = factory.getObject();
      }
   }
   catch (FactoryBeanNotInitializedException ex) {
      throw new BeanCurrentlyInCreationException(beanName, ex.toString());
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
   }

   // Do not accept a null value for a FactoryBean that's not fully
   // initialized yet: Many FactoryBeans just return null then.
   if (object == null) {
      if (isSingletonCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(
               beanName, "FactoryBean which is currently in creation returned null from getObject");
      }
      object = new NullBean();
   }
   return object;
}

忽略一些 try-catch 的一些代码,我们可以清晰的看到调用了 FactoryBeangetObject() 方法获得 bean。在最开始程序还对权限进行认证,如果设置了权限的话,先确认获得权限才能调用 getObject() 方法获得 bean。关于 Java 的权限相关,参考文末文章。

我们再回到 getObjectFromFactoryBean() 方法,通过 doGetObjectFromFactoryBean(factory, beanName) 方法创建出 bean 并没有直接返回,首先再次判断缓存中是否有,如果有那么用缓存的 bean 返回,没问题。如果确认缓存没有,那么理论上应该直接返回,但是并没有。Spring还调用 ObjectFactory 的后处理器对 bean 进行处理。我们查看子类 AbstractAutowireCapableBeanFactorypostProcessObjectFromFactoryBean(object, beanName) 方法:

/**
 * FactoryBean调用getObject()产生的bean的后处理操作
 * Applies the {@code postProcessAfterInitialization} callback of all
 * registered BeanPostProcessors, giving them a chance to post-process the
 * object obtained from FactoryBeans (for example, to auto-proxy them).
 * @see #applyBeanPostProcessorsAfterInitialization
 */
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
   return applyBeanPostProcessorsAfterInitialization(object, beanName);
}

/**
 * @param existingBean the new bean instance FactoryBean的getObject获得的对象
 * @param beanName the name of the bean 处理后的bean name
 * @return
 * @throws BeansException
 */
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

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

对于后处理器的使用,我们目前还没接触,后续会有大量篇幅介绍,这里我们只需要了解在Spring获取 bean 的规则中有这样一条:尽可能保证所有 bean 初始化后都会调用注册的 BeanPostProcessorpostProcessAfterInitialization 方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务处理。

V. 获取单例

我们已经将 bean 的加载流程分析到第三步结束,我们先放一放流程,先来研究一下和从缓存中获取 bean 相似的功能。在本文第三节介绍Spring创建单例 bean 首先到缓存中获取,如果获取不到则需要创建。注意,这里说的创建的 bean 是指创建初始状态的 bean,而不是第四节内容所说转换过的 bean Spring使用 getSingleton(String beanName, ObjectFactory singletonFactory) 重载方法实现 bean 的创建过程。

/**
 * 缓存中没有需要新创建单例初始状态的bean
 * Return the (raw) singleton object registered under the given name,
 * creating and registering a new one if none registered yet.
 * @param beanName the name of the bean
 * @param singletonFactory the ObjectFactory to lazily create the singleton
 * with, if necessary
 * @return the registered singleton object
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   // 全局变量需要同步
   synchronized (this.singletonObjects) {
      // 首先检查对应的bean是否已经加载过,因为是单例模式的,如果有直接返回
      Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) {
         // 单例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 + "'");
         }

         // 记录加载状态,通过this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中,
         // 便于对循环依赖进行检测
         beforeSingletonCreation(beanName);

         // 创建单例bean是否成功的标识
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
            // 初始化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;
            }

            // 创建完bean之后需要移除缓存中对该bean正在加载状态的记录
            afterSingletonCreation(beanName);
         }
         // 加入缓存并删除加载bean过程中所记录的各种辅助状态
         if (newSingleton) {
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

上述代码中其实使用了回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,而真正获取单例 bean 的方法其实并不是在此方法中实现的,其实现逻辑是在 ObjectFactory 类型的实例 singletonFactory 中实现的。我们看一下调用 getSingleton() 函数就明白了。

if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, () -> {
      try {
         // 核心所在
         return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
         // Explicitly remove instance from singleton cache: It might have been put there
         // eagerly by the creation process, to allow for circular reference resolution.
         // Also remove any beans that received a temporary reference to the bean.
         destroySingleton(beanName);
         throw ex;
      }
   });
   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

分析 getSingleton() 方法流程,我们大致可以了解到其在单例创建的前后做的一些准备及处理操作包括:

  1. 检查缓存是否已经加载过;

  2. 如果加载过直接返回缓存中的 bean;如果没有加载,则记录 beanName 的正在加载状态 ;

  3. 加载单例前记录加载状态;

    可能你会觉得 beforeSingletonCreation(beanName) 方法是个空实现,里面没有任何逻辑,但其实这个函数中做了一个很重要的操作:记录加载状态,也就是通过 this.singletonsCurrentlyInCreation.add(beanName) 将当前正要创建的 bean 记录在缓存中,这样便可以对循环依赖进行检测。

    protected void beforeSingletonCreation(String beanName) {
       if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
          throw new BeanCurrentlyInCreationException(beanName);
       }
    }
    
  4. 通过调用参数传入的 ObjectFactorygetObject 方法实例化 bean

  5. 加载单例后的处理方法调用;

    同步骤 3 的记录加载状态相似,当 bean 加载结束后需要移除缓存中对该 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");
        }
    }
    
  6. 将结果记录至缓存并删除加载 bean 过程中所记录的各种辅助状态;

    /**
     * 添加缓存并移除辅助变量
     * Add the given singleton object to the singleton cache of this factory.
     * <p>To be called for eager registration of singletons.
     * @param beanName the name of the bean
     * @param singletonObject the singleton object
     */
    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);
        }
    }
    
  7. 返回处理结果。

以上 7 个步骤就是创建初始状态 bean 的流程,其核心是第 4 步调用 singletonFactorygetObject 方法。该方法是在传入的 ObjectFactory 类型参数中定义的,其核心其实就是:

return createBean(beanName, mbd, args);

我们还需要去研究一波 createBean(beanName, mbd, args) 方法。

VI. 准备创建bean

理论上,这一部分确实到了该讲 createBean() 方法部分,标题该写为创建 bean,而不是准备。但是按照Spring一贯的编写风格,真正创建 bean 的工作肯定是交给 doXxx() 方法去完成,所以该部分主要研究Spring的createBean() 方法中在 doCreateBean() 之前先进行了哪些准备工作。

/**
 * 创建单例bean的核心之处
 * Central method of this class: creates a bean instance,
 * populates the bean instance, applies post-processors, etc.
 * @see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   // 锁定class,根据设置的class属性或者根据className来解析Class
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   // 当解析出class同时mbd中beanClass属性设置为字符串对象而不是Class对象时,需要对mbd进行更新为Class类型
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

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

   try {
      // 对BeanDefinition中的属性做些前置处理,给BeanPostProcessors一个机会来返回代理来替代真正的实例
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      // 如果前置处理返回的不为空,则直接返回(AOP功能就是这里判断的),否则需要进行常规bean的创建
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      // 真正创建常规bean
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isDebugEnabled()) {
         logger.debug("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}

代码的处理流程大致如下:

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

我们接下来详细看看每一步怎么操作的。

① 解析获取Class

Spring要创建 bean,需要先知道 bean 的具体类型。XML配置文件信息之前全部转换为 BeanDefinition 的形式。BeanDefinition 类中和 bean 的类型相关的属性为:

/**
 * bean的Class类型,对应bean的属性class
 */
@Nullable
private volatile Object beanClass;

在开始我们对于该属性赋值为 String 类型的 class 名称,而这一步骤的工作就是确保该属性类型是 Class 类型,可以由 class 名称进行转换。createBean() 中通过 resolveBeanClass(mbd, beanName) 方法来进行处理:

/**
 * Resolve the bean class for the specified bean definition,
 * resolving a bean class name into a Class reference (if necessary)
 * and storing the resolved Class in the bean definition for further use.
 * @param mbd the merged bean definition to determine the class for
 * @param beanName the name of the bean (for error handling purposes)
 * @param typesToMatch the types to match in case of internal type matching purposes
 * (also signals that the returned {@code Class} will never be exposed to application code)
 * @return the resolved bean class (or {@code null} if none)
 * @throws CannotLoadBeanClassException if we failed to load the class
 */
@Nullable
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
      throws CannotLoadBeanClassException {
   try {
      // mbd中是否含有class信息,而且是Class类型的,有则直接返回
      if (mbd.hasBeanClass()) {
         return mbd.getBeanClass();
      }
      // 没有则需要通过doResolveBeanClass()获取
      if (System.getSecurityManager() != null) {
         return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
            doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
      }
      else {
         return doResolveBeanClass(mbd, typesToMatch);
      }
   }
   catch (PrivilegedActionException pae) {
      ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   }
   catch (ClassNotFoundException ex) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   }
   catch (LinkageError err) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
   }
}

同样,如果 BeanDefinition 中本身就已经存储的是 Class 属性的 beanClass,那么直接返回即可。否则,需要委托 doResolveBeanClass(mbd, typesToMatch)String 类型的 beanClass 转换为 Class 类型。

@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
      throws ClassNotFoundException {

   ClassLoader beanClassLoader = getBeanClassLoader();
   ClassLoader classLoaderToUse = beanClassLoader;
   if (!ObjectUtils.isEmpty(typesToMatch)) {
      // When just doing type checks (i.e. not creating an actual instance yet),
      // use the specified temporary class loader (e.g. in a weaving scenario).
      ClassLoader tempClassLoader = getTempClassLoader();
      if (tempClassLoader != null) {
         classLoaderToUse = tempClassLoader;
         if (tempClassLoader instanceof DecoratingClassLoader) {
            DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
            for (Class<?> typeToMatch : typesToMatch) {
               dcl.excludeClass(typeToMatch.getName());
            }
         }
      }
   }
   // String类型的beanClass转换
   String className = mbd.getBeanClassName();
   if (className != null) {
      Object evaluated = evaluateBeanDefinitionString(className, mbd);
      if (!className.equals(evaluated)) {
         // A dynamically resolved expression, supported as of 4.2...
         if (evaluated instanceof Class) {
            return (Class<?>) evaluated;
         }
         else if (evaluated instanceof String) {
            return ClassUtils.forName((String) evaluated, classLoaderToUse);
         }
         else {
            throw new IllegalStateException("Invalid class name expression result: " + evaluated);
         }
      }
      // When resolving against a temporary class loader, exit early in order
      // to avoid storing the resolved Class in the bean definition.
      if (classLoaderToUse != beanClassLoader) {
         return ClassUtils.forName(className, classLoaderToUse);
      }
   }
   return mbd.resolveBeanClass(beanClassLoader);
}

转换好后,我们需要更新一下 BeanDefinitionbeanClass 属性。

// 锁定class,根据设置的class属性或者根据className来解析Class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 当解析出class同时mbd中beanClass属性设置为字符串对象而不是Class对象时,需要对mbd进行更新为Class类型
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    mbdToUse = new RootBeanDefinition(mbd);
    mbdToUse.setBeanClass(resolvedClass);
}

② 验证override及准备覆盖的方法

其实在Spring中确实没有 override-method 这样的配置,但是我们前面说过,在Spring配置中是存在 lookup-methodreplace-method 的,而这个两个配置的加载其实就是将配置统一存放在 BeanDefinition 中的 methodOverrides 属性里,而这个函数的操作其实也就是针对于这两个配置的。我们先看看 Override 属性标记及验证的逻辑实现。查看Spring的 AbstractBeanDefinition 类的 prepareMethodOverrides() 方法:

/**
 * 验证并准备该bean的method-overrides
 * Validate and prepare the method overrides defined for this bean.
 * Checks for existence of a method with the specified name.
 * @throws BeanDefinitionValidationException in case of validation failure
 */
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   // Check that lookup methods exists.
   if (hasMethodOverrides()) {
      Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
      synchronized (overrides) {
         for (MethodOverride mo : overrides) {
            prepareMethodOverride(mo);
         }
      }
   }
}

/**
 * Validate and prepare the given method override.
 * Checks for existence of a method with the specified name,
 * marking it as not overloaded if none found.
 * @param mo the MethodOverride object to validate
 * @throws BeanDefinitionValidationException in case of validation failure
 */
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    // 获取对应类中对应方法名的个数
    int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
    if (count == 0) {
        throw new BeanDefinitionValidationException(
            "Invalid method override: no method with name '" + mo.getMethodName() +
            "' on class [" + getBeanClassName() + "]");
    }
    else if (count == 1) {
        // 标记MethodOverride暂未被重载,避免参数类型检查的开销
        mo.setOverloaded(false);
    }
}

bean 实例化的时候如果检测到存在 methodOverrides 属性,会动态地为当前 bean 生成代理并使用对应的拦截器为 bean 做增强处理,相关的逻辑实现在 bean 的实例化部分详细介绍。

这里要提到的是,对于方法的匹配来讲,如果一个类中存在若干个重载方法,那么在函数调用及增强的时候还需要根据参数类型进行匹配,来最终确认当前调用的到底是哪个函数。但是Spring将一部分匹配工作在这里完成了,如果当前类中的方法只有一个,那就设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要进行方法的参数匹配验证了,而且还可以提前对方法存在性进行验证,正可谓一举两得。

③ 实例化的前置处理

回到 createBean() 方法中,在 doCreateBean 方法前使用了 resolveBeforeInstantiation(beanName, mbdToUse) 方法,此方法是对 BeanDefinition 中的属性做了一些前置处理。

// 对BeanDefinition中的属性做些前置处理,给BeanPostProcessors一个机会来返回代理来替代真正的实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果前置处理返回的不为空,则直接返回(AOP功能就是这里判断的),否则需要进行常规bean的创建
if (bean != null) {
   return bean;
}

当然,resolveBeforeInstantiation(beanName, mbdToUse) 方法中Spring究竟处没处理相对不是非常的重要,毕竟相当于在创建 bean 之前预留了接口进行预处理操作,可以供我们自定义实现。同时函数还提供了一个短路判断,如果预处理完返回的 bean 不为空,则直接返回,跳过下面 doCreateBean 方法。我们熟悉的AOP功能就是基于这个判断的。知道这些,我们再来具体研究 resolveBeforeInstantiation(beanName, mbdToUse) 方法:

/**
 * 对BeanDefinition中的属性做些前置处理
 * Apply before-instantiation post-processors, resolving whether there is a
 * before-instantiation shortcut for the specified bean.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @return the shortcut-determined bean instance, or {@code null} if none
 */
@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.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            // 在bean的实例化前会调用后处理器的方法进行处理
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               // 实例化后的后处理器应用
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

此方法内部分别对 bean 初始化前后的后处理器进行了调用。

实例化前的后处理器调用

bean 的实例化前进行调用,也就是将 AbsractBeanDefinition 转换为 BeanWrapper 前的处理。给子类一个修改 BeanDefinition 的机会,也就是说当程序经过这个方法后,,bean 可能已经不是我们认为的 bean 了,而是或许成为了一个经过处理的代理 bean,可能是通过 cglib 生成的,也可能是通过其它技术生成的。后面讲AOP时会再详细介绍,现在只需要知道,在 bean 的实例化前会调用后处理器的方法进行处理。

/**
 * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
 * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
 * <p>Any returned object will be used as the bean instead of actually instantiating
 * the target bean. A {@code null} return value from the post-processor will
 * result in the target bean being instantiated.
 * @param beanClass the class of the bean to be instantiated
 * @param beanName the name of the bean
 * @return the bean object to use instead of a default instance of the target bean, or {@code null}
 * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
 */
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
         Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
         if (result != null) {
            return result;
         }
      }
   }
   return null;
}

实例化后的后处理器调用

在讲解从缓存中获取单例 bean 中从工厂 bean 的实例中获取对象环节(本文第IV部分)的时候就提到过, Spring中有一个规则是在 bean 的初始化后尽可能保证将注册的后处理器的 postProcessAfterInitialization 方法应用到该 bean 中,因为如果返回的 bean 不为空,短路判断那么便不会再次经历普通 bean 的创建过程,所以只能在这里应用后处理器的 postProcessAfterInitialization() 方法。

/**
 * @param existingBean the new bean instance FactoryBean的getObject获得的对象
 * @param beanName the name of the bean 处理后的bean name
 * @return
 * @throws BeansException
 */
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

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

createBean() 中所有的准备工作做完了,就可以调用 doCreateBean() 真正的创建常规 bean。在分析 doCreateBean() 之前,我们先说一下Spring中的循环依赖问题解决。

VII. 循环依赖

循环依赖

如图,简单来说,就是 A 类中引用了 B,B 类中引用了 A,互相引用,互相依赖。同样,A 引用 B,B 引用 C,C 引用 A也构成循环依赖。

循环依赖

Spring容器的循环依有:

  • 构造器的循环依赖
  • setter方法的循环依赖

Spring解决循环依赖方案

① 构造器循环依赖

表示利用构造函数注入构成了循环依赖,这种方式下是无法解决的,只能抛出 BeanCurrentlyInCreationException 异常表示循环依赖。我们先构造三个实体类,发生构造器循环依赖。

public class A {
    private B b;

    public A(B b) {
        this.b = b;
    }
}

public class B {
    private C c;

    public B(C c) {
        this.c = c;
    }
}

public class C {
	private A a;

	public C(A a) {
		this.a = a;
	}
}

Spring在创建 A 类时,构造器需要 B 类,那么将去创建 B;在创建 B 的时候,又发现需要 C 类,则又去创建 C 类;最终在创建 C 类的时候发现又需要 A,从而形成环,这种情况下Spring是无法解决的。

Spring容器将每一个正在创建的 bean 的标识符放在一个 “当前创建 bean 池” 中,bean 标识符在创建过程中将一直保持在这个池中,因此如果在创建 bean 过程中发现自己已经在 “当前创建 bean 池” 里时,将抛出 BeanCurrentlyInCreationException 异常表示循环依赖。而对于创建完成的 bean 将从 “当前创建 bean 池” 里清除。

我们来测试一下,编写对应的配置文件:

<?xml version='1.0' encoding='UTF-8' ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="a" class="guo.ping.ioc.circledependency.A">
        <constructor-arg ref="b" />
    </bean>

    <bean id="b" class="guo.ping.ioc.circledependency.B">
        <constructor-arg ref="c" />
    </bean>

    <bean id="c" class="guo.ping.ioc.circledependency.C">
        <constructor-arg ref="a" />
    </bean>
</beans>

spring-mytest 模块中添加测试文件:

public class CircleDependencyTest {
   @Test
   public void testCircleDependency() {
      ClassPathResource resource = new ClassPathResource("circleDependency-Test.xml");
      BeanFactory beanFactory = new XmlBeanFactory(resource);
      A a = (A) beanFactory.getBean("a");
   }
}

测试结果:

构造器循环依赖

② setter循环依赖

这种情况,表示通过 setter 注入方式构成的循环依赖。对于 setter 注入的循环依赖Spring能够通过提前暴露刚完成构造器构造但未完成其他步骤(如 setter 注入)的 bean 来解决的。值得注意的是,这种方式只能解决单例作用域的 bean 循环依赖。

Spring通过提前暴露一个单例工厂对象,从而使其他 bean 能通过该工厂对象的 getObject() 引用到该 bean。这在本文前面已经有所涉及。Spring为了解决单例 setter 的循环依赖,设置了三级缓存机制。

/** 一级缓存 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** 二级缓存 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

/** 三级缓存 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
  • singletonObjects:单例对象的缓存
  • earlySingletonObjects :提前曝光的单例对象的缓存
  • singletonFactories : 单例对象工厂的缓存

Spring首先从一级缓存 singletonObjects 中获取,如果获取不到,并且对象正在创建中,就再从二级缓存 earlySingletonObjects 中获取。如果还是获取不到且允许 singletonFactories 通过 getObject() 获取,就从三级缓存 singletonFactory.getObject() 中获取。一旦从三级缓存中获取到了,将 singletonFactories 中移除掉缓存,并将创建出的 bean 放入 earlySingletonObjects 中,其实也就是从三级缓存移动到了二级缓存。

我们再来测试一下:

public class D {
   private E e;
   public E getE() {
      return e;
   }
   public void setE(E e) {
      this.e = e;
   }
}

public class E {
	private F f;
	public F getF() {
		return f;
	}
	public void setF(F f) {
		this.f = f;
	}
}

public class F {
	private D d;
	public D getD() {
		return d;
	}
	public void setD(D d) {
		this.d = d;
	}
}

配置文件:

<?xml version='1.0' encoding='UTF-8' ?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="d" class="guo.ping.ioc.circledependency.D">
      <property name="e" ref="e" />
   </bean>

   <bean id="e" class="guo.ping.ioc.circledependency.E">
      <property name="f" ref="f" />
   </bean>

   <bean id="f" class="guo.ping.ioc.circledependency.F">
      <property name="d" ref="d" />
   </bean>
</beans>

测试方法:

D d = (D) beanFactory.getBean("d");

测试结果:

setter循环依赖

测试结果表明,Spring能够解决单例模式下 setter 循环依赖问题。具体的步骤可以解读为:

  1. Spring创建单例 d 名称的 bean 时,首先根据无参构造器创建 bean,并暴露一个 ObjectFactory 能够用于提前返回暴露一个创建中的 bean,将这个 ObjectFactory 放入三级缓存;
  2. 当需要给 d 进行属性注入 (populateBean) 过程时,发现其依赖 e,所以便转去创建 e。同样,创建单例 e 名称的 bean 时,首先根据无参构造器创建 bean,并暴露一个 ObjectFactory 能够用于提前返回一个创建中的 bean,将这个 ObjectFactory 放入三级缓存;
  3. 类似的,给 e 进行属性注入的过程时,去创建了单例 f,并暴露一个 ObjectFactory 放入三级缓存。
  4. 当给 f 注入属性 d 时,由于三级缓存中存放了能够获取创建一半的 dObjectFactory,通过调用 getObject() 获取半成品,并将其注入 f

这样循环依赖便解决了。

③ prototype范围的依赖处理

对于 prototype 作用域,Spring是无法解决循环依赖的。如果对于上面 setter 循环依赖的解决思路,不难推理出这一结论,Spring容器的缓存机制对于 prototype 是失效的。

对于 singletonbean,可以通过 XmlBeanFactory.setAllowCircularReferences(false) 来禁用循环依赖,这样就Spring不会尝试解决这一问题,直接抛出异常。

最后有必要补充,在单例模式下,如果构造器与 setter 混搭形成循环依赖,能否解决就要看环的切入点了。如果第一个要创建的就是构造器的将会抛出异常,如果第一个要创建的是 setter 注入的,Spring也能解决。

VIII. (do)创建bean

中间一波循环依赖的小插曲,希望大家没有被打断思路。我们在 VI 部分说到创建 bean 前的准备工作,回顾一下代码:

/**
 * 创建单例bean的核心之处
 * Central method of this class: creates a bean instance,
 * populates the bean instance, applies post-processors, etc.
 * @see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   // 锁定class,根据设置的class属性或者根据className来解析Class
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   // 当解析出class同时mbd中beanClass属性设置为字符串对象而不是Class对象时,需要对mbd进行更新为Class类型
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

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

   try {
      // 对BeanDefinition中的属性做些前置处理,给BeanPostProcessors一个机会来返回代理来替代真正的实例
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      // 如果前置处理返回的不为空,则直接返回(AOP功能就是这里判断的),否则需要进行常规bean的创建
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      // 真正创建常规bean
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isDebugEnabled()) {
         logger.debug("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}

我们说到了短路操作结束,如果前置处理返回的 bean 为空,那么下面就要进行常规 bean 的创建,也就是 doCreateBean 方法。

/**
 * 真正创建常规bean的地方
 * Actually create the specified bean. Pre-creation processing has already happened
 * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
 * <p>Differentiates between default bean instantiation, use of a
 * factory method, and autowiring a constructor.
 * @param beanName the name of the bean
 * @param mbd the merged bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return a new instance of the bean
 * @throws BeanCreationException if the bean could not be created
 * @see #instantiateBean
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   // 如果是单例,先清除缓存
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // 根据指定bean使用对应的策略创建新的实例,如:工厂方法、构造函数自动注入、简单初始化
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   final Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         // 应用MergedBeanDefinitionPostProcessors
         try {
            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正在创建中,检测循环依赖
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
         logger.debug("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      // 为避免后期循环依赖,可以在bean初始化完成之前将创建实例的ObjectFactory加入工厂
      addSingletonFactory(beanName,
            // 对bean再一次依赖引用,主要应用SmartInstantiationAware BeanPostProcessor
            // 其中我们熟知的AOP就是这样将advice动态织入bean中,若没有则直接返回bean,不做任何处理
            () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      // 对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始依赖bean
      populateBean(beanName, mbd, instanceWrapper);
      // 调用初始化方法,比如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);
      }
   }

   if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      // earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
      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创建后其依赖的bean却没有没全部创建完,也就是说存在循环依赖
            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.");
            }
         }
      }
   }

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

   return exposedObject;
}

好家伙,这方法内容也太多了,我们忽略掉一些基本 try-catch 异常代码与日志代码,梳理一下思路:

  1. 如果是单例模式,首先从缓存中尝试 remove 得到 BeanWrapper
  2. 如果缓存中没有,则根据 BeanDefinition 转换为 BeanWrapper
  3. 通过前两步,我们得到 BeanWrapper 后,进行 MergedBeanDefinitionPostProcessors 的应用。主要是 bean 合并后的处理,@AutoWire 就是基于这个方法实现诸如类型的预解析;
  4. 处理 bean 的依赖;
  5. 对bean进行填充,将各个属性值注入 bean
  6. 循环依赖检查,检测已经加载的 bean 是否已经出现了依赖循环,并判断是否要抛出异常;
  7. 注册 DisposableBean。如果XML配置了 destory-method,这里需要注册以便于销毁 bean 的时候调用;
  8. 完成创建并返回。

下面还是继续按部就班一步步来理解:

获取BeanWrapper

在之前我们已经了解过循环依赖,我们先了解一下 BeanWrapper 类的作用。Spring中 BeanDefinition 提供数据,然后 BeanWrapper 负责依赖注入。BeanWrapper 相当于一个代理器,Spring委托 BeanWrapper 完成 bean 属性的填充工作,具体是由 BeanWrapper 的实现类 BeanWrapperImpl 来完成的。

首先先从缓存中获取 BeanWrapper 对象,从 factoryBeanInstanceCache 中进行 remove,如果获取成功,则没什么。如果缓存中没有,我们需要调用 createBeanInstance() 方法根据指定 bean 使用对应的策略创建新的 BeanWrapper 实例。

/**
 * 创建beanWrapper的实例
 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
 * factory method, constructor autowiring, or simple instantiation.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return a BeanWrapper for the new instance
 * @see #obtainFromSupplier
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 * @see #instantiateBean
 */
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   // Make sure bean class is actually resolved at this point.
   // 解析class
   Class<?> beanClass = resolveBeanClass(mbd, beanName);

   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }

   // 有指定的Supplier获取bean(JDK8 Spring5)
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
   }

   // 如果mbd中factoryMethodName不为空,则使用工厂方法初始化策略
   if (mbd.getFactoryMethodName() != null)  {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

   // Shortcut when re-creating the same bean...
   boolean resolved = false;
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
         // 一个类有多个构造函数,每个构造函数都有不同的参数,所以调用前需要先根据参数锁定构造函数和对应的工厂方法
         // resolvedConstructorOrFactoryMethod缓存这构造函数或工厂方法
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
   // 如果已经解析过则使用缓存中已经解析好的构造函数方法不需要再次锁定
   if (resolved) {
      if (autowireNecessary) {
         // 构造函数自动注入
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
         // 使用默认构造函数构造
         return instantiateBean(beanName, mbd);
      }
   }

   // 需要根据参数解析构造函数...
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      // 构造函数自动注入
      return autowireConstructor(beanName, mbd, ctors, args);
   }

   // 没有特殊则使用默认构造函数构造
   return instantiateBean(beanName, mbd);
}

代码逻辑为:

(1)如果在 RootBeanDefinition 中存在 instanceSupplier 属性,那么Spring会尝试使用 obtainFromSupplier(instanceSupplier, beanName) 方法根据 instanceSupplierget() 方法生成实例,关于 Supplier 具体参考文末文章

(2)如果在 RootBeanDefinition 中存在 factoryMethodName 属性,或者再配置文件中配置了 factory-method,那么Spring会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法根据 RootBeanDefinition 中的配置生成实例;

(3)解析构造函数并进行构造函数的实例化,因为一个 bean 可能会有多个构造函数,而每个构造函数的参数不同,Spring在根据参数及类型去判断最终会使用哪个构造函数进行实例化。而这个判断过程非常的消耗性能,因此Spring采用了缓存机制,如果已经解析过了则不需要重复解析而直接从 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 中去取,否则需要再次解析,并将解析结果添加到 RootBeanDefinitionresolvedConstructorOrFactoryMethod 中。

前两步我们先放一放,先看第三步中的两个核心函数:autowireConstructorinstantiateBean

① autowireConstructor

对于实例的创建Spring中分成了两种情况,一种是通用的实例化,另一种是带有参数的实例化。带有参数的实例化过程相当复杂,因为存在着不确定性,所以在判断对应参数上做了大量工作。

/**
 * 带有参数的构造方法实例化
 * "autowire constructor" (with constructor arguments by type) behavior.
 * Also applied if explicit constructor argument values are specified,
 * matching all remaining arguments with beans from the bean factory.
 * <p>This corresponds to constructor injection: In this mode, a Spring
 * bean factory is able to host components that expect constructor-based
 * dependency resolution.
 * @param beanName the name of the bean
 * @param mbd the merged bean definition for the bean
 * @param chosenCtors chosen candidate constructors (or {@code null} if none)
 * @param explicitArgs argument values passed in programmatically via the getBean method,
 * or {@code null} if none (-> use constructor argument values from bean definition)
 * @return a BeanWrapper for the new instance
 */
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
      @Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) {

   BeanWrapperImpl bw = new BeanWrapperImpl();
   this.beanFactory.initBeanWrapper(bw);

   Constructor<?> constructorToUse = null;
   ArgumentsHolder argsHolderToUse = null;
   Object[] argsToUse = null;

   // explicitArgs通过getBean方法传入
   // 如果getBean方法调用的时候指定了方法参数那么直接使用
   if (explicitArgs != null) {
      argsToUse = explicitArgs;
   }
   // 如果getBean方法调用的时候没有指定方法参数则尝试从缓存中解析
   else {
      Object[] argsToResolve = null;
      // 尝试从缓存中获取
      synchronized (mbd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse != null && mbd.constructorArgumentsResolved) {
            // 从缓存中获取
            argsToUse = mbd.resolvedConstructorArguments;
            if (argsToUse == null) {
               // 配置的构造函数参数
               argsToResolve = mbd.preparedConstructorArguments;
            }
         }
      }
      // 如果缓存中存在
      if (argsToResolve != null) {
         // 解析参数类型,如给定方法的构造函数A(int, int)则通过此方法后就会把配置中的("1", "1")转换为(1, 1)
         // 缓存中的值可能是原始值也可能是最终值
         argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
      }
   }

   // 如果没有被缓存,则从配置文件的配置下手
   if (constructorToUse == null) {
      // Need to resolve the constructor.
      boolean autowiring = (chosenCtors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
      ConstructorArgumentValues resolvedValues = null;

      int minNrOfArgs;
      if (explicitArgs != null) {
         minNrOfArgs = explicitArgs.length;
      }
      else {
         // 提取配置文件中的配置的构造函数参数
         ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
         // 用于承载解析后的构造函数参数的值
         resolvedValues = new ConstructorArgumentValues();
         // 能解析到的参数个数
         minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
      }

      // Take specified constructors, if any.
      Constructor<?>[] candidates = chosenCtors;
      if (candidates == null) {
         Class<?> beanClass = mbd.getBeanClass();
         try {
            candidates = (mbd.isNonPublicAccessAllowed() ?
                  beanClass.getDeclaredConstructors() : beanClass.getConstructors());
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                  "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
         }
      }
      // 排序给定的构造函数,public构造函数优先参数数量降序、非public构造函数参数数量降序
      AutowireUtils.sortConstructors(candidates);
      
      int minTypeDiffWeight = Integer.MAX_VALUE;
      Set<Constructor<?>> ambiguousConstructors = null;
      LinkedList<UnsatisfiedDependencyException> causes = null;

      for (Constructor<?> candidate : candidates) {
         // 获取每个构造函数其所有的参数类型组成数组(不去重)
         Class<?>[] paramTypes = candidate.getParameterTypes();

         if (constructorToUse != null && argsToUse.length > paramTypes.length) {
            // 如果已经找到该用的构造函数并且用的参数大于构造函数可以传入的,因为降序排序,所以一旦大于,后面都会大于
            break;
         }
         if (paramTypes.length < minNrOfArgs) {
            // 文件配置的参数多于构造函数可以传入的,则进行下一个尝试
            continue;
         }

         ArgumentsHolder argsHolder;
         if (resolvedValues != null) {
            // 有参数则根据值构造对应参数类型的参数
            try {
               // 注解上获取参数名称
               String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
               if (paramNames == null) {
                  // 获取参数名称探索器
                  ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                  if (pnd != null) {
                     // 获取指定构造函数的参数名称
                     paramNames = pnd.getParameterNames(candidate);
                  }
               }
               // 根据名称和数据类型创建参数持有者
               argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
                     getUserDeclaredConstructor(candidate), autowiring);
            }
            catch (UnsatisfiedDependencyException ex) {
               if (logger.isTraceEnabled()) {
                  logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
               }
               // Swallow and try next constructor.
               if (causes == null) {
                  causes = new LinkedList<>();
               }
               causes.add(ex);
               continue;
            }
         }
         else {
            // Explicit arguments given -> arguments length must match exactly.
            if (paramTypes.length != explicitArgs.length) {
               continue;
            }
            // 构造函数没有参数的情况
            argsHolder = new ArgumentsHolder(explicitArgs);
         }

         // 探测是否有不确定的构造函数存在,例如不同构造函数的参数为父子关系
         int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
               argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
         // 如果他代表着当前最接近的匹配则选择作为构造函数
         if (typeDiffWeight < minTypeDiffWeight) {
            constructorToUse = candidate;
            argsHolderToUse = argsHolder;
            argsToUse = argsHolder.arguments;
            minTypeDiffWeight = typeDiffWeight;
            ambiguousConstructors = null;
         }
         else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
            if (ambiguousConstructors == null) {
               ambiguousConstructors = new LinkedHashSet<>();
               ambiguousConstructors.add(constructorToUse);
            }
            ambiguousConstructors.add(candidate);
         }
      }

      if (constructorToUse == null) {
         if (causes != null) {
            UnsatisfiedDependencyException ex = causes.removeLast();
            for (Exception cause : causes) {
               this.beanFactory.onSuppressedException(cause);
            }
            throw ex;
         }
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Could not resolve matching constructor " +
               "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
      }
      else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Ambiguous constructor matches found in bean '" + beanName + "' " +
               "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
               ambiguousConstructors);
      }

      if (explicitArgs == null) {
         // 将解析的构造函数加入缓存
         argsHolderToUse.storeCache(mbd, constructorToUse);
      }
   }

   try {
      final InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
      Object beanInstance;

      if (System.getSecurityManager() != null) {
         final Constructor<?> ctorToUse = constructorToUse;
         final Object[] argumentsToUse = argsToUse;
         beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
               strategy.instantiate(mbd, beanName, this.beanFactory, ctorToUse, argumentsToUse),
               this.beanFactory.getAccessControlContext());
      }
      else {
         beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
      }
      // 将构建的实例加入BeanWrapper中
      bw.setBeanInstance(beanInstance);
      return bw;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean instantiation via constructor failed", ex);
   }
}

又是巨大的代码量,希望你没有迷失在里面,一定要保持逻辑清楚。我们总览一下整个函数,其实现的功能考虑了以下几个方面:

a. 构造函数参数的确定
  • 根据 explicitArgs 参数判断

    如果调用函数时传入的 explicitArgs 参数不为空,那么可以直接确认构造函数的参数就是这个。我们回溯一下 explicitArgs 参数的来源:

    Object getBean(String name, Object... args) throws BeansException;
    

    在获取 bean 的时候,用户不但可以指定 bean 的名称还可以指定 bean 所对应的构造函数或者工厂方法的方法参数,主要用于静态工厂方法的调用,而这里是需要给定完全匹配的参数的。所以,只要传入了 explicitArgs 参数,就是构造函数的参数了。

    if (explicitArgs != null) {
       argsToUse = explicitArgs;
    }
    
  • 缓存中获取

    如果 explicitArgs 参数为空,便可以先尝试从缓存中获取。缓存中缓存了构造函数的参数,但是参数可能是最终类型,也可能是初始类型。比如:构造函数参数要求的是 int 类型,但初始的参数值可能是 String 类型的 “1”,那么即使从缓存中获取到参数,也需要进行类型转换器的过滤确保参数类型完全对应上。

    从代码上来看,argsToResolve 则是保存最后类型对应上的参数,它可能来自于 mbd.resolvedConstructorArguments,但是如果没有,则需要从缓存保存的初始参数 mbd.preparedConstructorArguments 通过 resolvePreparedArguments() 方法来进行转换。

    // 如果getBean方法调用的时候没有指定方法参数则尝试从缓存中解析
    else {
       Object[] argsToResolve = null;
       // 尝试从缓存中获取
       synchronized (mbd.constructorArgumentLock) {
          constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
          if (constructorToUse != null && mbd.constructorArgumentsResolved) {
             // 从缓存中获取已解析好的构造函数参数
             argsToUse = mbd.resolvedConstructorArguments;
             if (argsToUse == null) {
                // 如果缓存中没有,则通过配置的(准备)构造函数参数来生成
                argsToResolve = mbd.preparedConstructorArguments;
             }
          }
       }
       // 如果缓存中存在
       if (argsToResolve != null) {
          // 解析参数类型,如给定方法的构造函数A(int, int)则通过此方法后就会把配置中的("1", "1")转换为(1, 1)
          // 缓存中的值可能是原始值也可能是最终值
          argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
       }
    }
    
  • 配置文件获取

    如果缓存中也没有,那么只能从 BeanDefinition 中去下手,也就是 mbd 参数,从中去解析出我们需要的参数信息。通过 mbd.getConstructorArgumentValues() 能够获取配置的构造函数信息。 有了配置的信息便可以解析对应的参数值信息了,resolveConstructorArguments() 方法获取参数值的信息包括直接指定值,如:直接指定构造函数中的某个值为原始类型 String 类型,或者是一个对其他 bean 的引用。

    // 如果没有被缓存,则从配置文件的配置下手
    if (constructorToUse == null) {
       // Need to resolve the constructor.
       boolean autowiring = (chosenCtors != null ||
             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
       ConstructorArgumentValues resolvedValues = null;
    
       int minNrOfArgs;
       if (explicitArgs != null) {
          minNrOfArgs = explicitArgs.length;
       }
       else {
          // 提取配置文件中的配置的构造函数参数
          ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
          // 用于承载解析后的构造函数参数的值
          resolvedValues = new ConstructorArgumentValues();
          // 能解析到的参数个数
          minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
       }
    

    具体看看 resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues) 的方法。该方法五个参数具体见注释,函数内部主要对参数个数的统计以及将 cargs 解析保存至 resolvedValues 中。

    /**
     * 确定构造函数参数,并保存到resolvedValues中
     * Resolve the constructor arguments for this bean into the resolvedValues object.
     * This may involve looking up other beans.
     * <p>This method is also used for handling invocations of static factory methods.
     * @param beanName bean名称
     * @param mbd 配置文件信息
     * @param bw beanwrapper
     * @param cargs 配置文件中解析出的构造函数信息
     * @param resolvedValues 保存解析出的参数值信息
     * @return 解析到参数的个数
     */
    private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
          ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
    
       TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
       TypeConverter converter = (customConverter != null ? customConverter : bw);
       BeanDefinitionValueResolver valueResolver =
             new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
    
       int minNrOfArgs = cargs.getArgumentCount();
    
       for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
          int index = entry.getKey();
          if (index < 0) {
             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                   "Invalid constructor argument index: " + index);
          }
          if (index > minNrOfArgs) {
             minNrOfArgs = index + 1;
          }
          ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
          if (valueHolder.isConverted()) {
             resolvedValues.addIndexedArgumentValue(index, valueHolder);
          }
          else {
             Object resolvedValue =
                   valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
             ConstructorArgumentValues.ValueHolder resolvedValueHolder =
                   new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
             resolvedValueHolder.setSource(valueHolder);
             resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
          }
       }
    
       for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
          if (valueHolder.isConverted()) {
             resolvedValues.addGenericArgumentValue(valueHolder);
          }
          else {
             Object resolvedValue =
                   valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
             ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
                   resolvedValue, valueHolder.getType(), valueHolder.getName());
             resolvedValueHolder.setSource(valueHolder);
             resolvedValues.addGenericArgumentValue(resolvedValueHolder);
          }
       }
    
       return minNrOfArgs;
    }
    
b. 构造函数的确定

经过上面构造函数参数的确定,我们可以依据参数来锁定构造函数。我们需要先获取所有的候选的构造函数,如果用户传入构造函数那么直接确定为候选集合,否则需要我们根据 bean 的类型获取其所有的构造函数:

// 获取所有的构造函数
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
   Class<?> beanClass = mbd.getBeanClass();
   try {
      // 是否包含非public的构造函数
      candidates = (mbd.isNonPublicAccessAllowed() ?
            beanClass.getDeclaredConstructors() : beanClass.getConstructors());
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Resolution of declared constructors on bean Class [" + beanClass.getName() +
            "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
   }
}

匹配构造函数的方法是根据参数个数进行匹配,所以匹配前需要先对构造函数按照 public 构造函数优先参数数量降序、非 public 构造函数参数数量降序。这样可以在遍历的情况下迅速判断排在后面的构造函数参数个数是否符合条件。

// 排序给定的构造函数,public构造函数优先参数数量降序、非public构造函数参数数量降序
AutowireUtils.sortConstructors(candidates);

public static void sortConstructors(Constructor<?>[] constructors) {
    Arrays.sort(constructors, (c1, c2) -> {
        boolean p1 = Modifier.isPublic(c1.getModifiers());
        boolean p2 = Modifier.isPublic(c2.getModifiers());
        if (p1 != p2) {
            return (p1 ? -1 : 1);
        }
        int c1pl = c1.getParameterCount();
        int c2pl = c2.getParameterCount();
        return (c1pl < c2pl ? 1 : (c1pl > c2pl ? -1 : 0));
    });
}

由于在配置文件中并不限制只能用参数位置索引的方式去创建,同样支持指定参数名称进行设定参数值的情况,例如 <constructor-arg name=“aa”>,那么这种情况就需要首先确定构造函数中的参数名称。

获取参数名称有两种方式,一种是注解的方式直接获取,另一种是使用Spring提供的工具类 ParamterNameDiscover 来获取。注解的方式如下:

@Nullable
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
   ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
   if (cp != null) {
      String[] names = cp.value();
      if (names.length != paramCount) {
         throw new IllegalStateException("Constructor annotated with @ConstructorProperties but not " +
               "corresponding to actual number of parameters (" + paramCount + "): " + candidate);
      }
      return names;
   }
   else {
      return null;
   }
}

如果注解获取不到,则需要借助 ParamterNameDiscover 来获取。

// 注解上获取参数名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
   // 获取参数名称探索器
   ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
   if (pnd != null) {
      // 获取指定构造函数的参数名称
      paramNames = pnd.getParameterNames(candidate);
   }
}

构造函数、参数名称、参数类型、参数值都确定后就可以锁定构造函数以及转换对应的参数类型了。

c. 根据确定的构造函数转换对应的参数类型

主要使用Spring中提供的类型转换器或者用户提供的自定义类型转换器进行转换。

/*
 * 将确定的构造函数转换为对应的参数类型
 * Create an array of arguments to invoke a constructor or factory method,
 * given the resolved constructor argument values.
 */
private ArgumentsHolder createArgumentArray(
      String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
      BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
      boolean autowiring) throws UnsatisfiedDependencyException {

   TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
   TypeConverter converter = (customConverter != null ? customConverter : bw);

   ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
   Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
   Set<String> autowiredBeanNames = new LinkedHashSet<>(4);

   for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
      Class<?> paramType = paramTypes[paramIndex];
      String paramName = (paramNames != null ? paramNames[paramIndex] : "");
      // Try to find matching constructor argument value, either indexed or generic.
      ConstructorArgumentValues.ValueHolder valueHolder = null;
      if (resolvedValues != null) {
         valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
         // If we couldn't find a direct match and are not supposed to autowire,
         // let's try the next generic, untyped argument value as fallback:
         // it could match after type conversion (for example, String -> int).
         if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
            valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
         }
      }
      if (valueHolder != null) {
         // We found a potential match - let's give it a try.
         // Do not consider the same value definition multiple times!
         usedValueHolders.add(valueHolder);
         Object originalValue = valueHolder.getValue();
         Object convertedValue;
         if (valueHolder.isConverted()) {
            convertedValue = valueHolder.getConvertedValue();
            args.preparedArguments[paramIndex] = convertedValue;
         }
         else {
            MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
            try {
               convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
            }
            catch (TypeMismatchException ex) {
               throw new UnsatisfiedDependencyException(
                     mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
                     "Could not convert argument value of type [" +
                           ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
                           "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
            }
            Object sourceHolder = valueHolder.getSource();
            if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
               Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
               args.resolveNecessary = true;
               args.preparedArguments[paramIndex] = sourceValue;
            }
         }
         args.arguments[paramIndex] = convertedValue;
         args.rawArguments[paramIndex] = originalValue;
      }
      else {
         MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
         // No explicit match found: we're either supposed to autowire or
         // have to fail creating an argument array for the given constructor.
         if (!autowiring) {
            throw new UnsatisfiedDependencyException(
                  mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
                  "Ambiguous argument values for parameter of type [" + paramType.getName() +
                  "] - did you specify the correct bean references as arguments?");
         }
         try {
            Object autowiredArgument =
                  resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter);
            args.rawArguments[paramIndex] = autowiredArgument;
            args.arguments[paramIndex] = autowiredArgument;
            args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
            args.resolveNecessary = true;
         }
         catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(
                  mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
         }
      }
   }

   for (String autowiredBeanName : autowiredBeanNames) {
      this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
      if (logger.isDebugEnabled()) {
         logger.debug("Autowiring by type from bean name '" + beanName +
               "' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
               " to bean named '" + autowiredBeanName + "'");
      }
   }

   return args;
}
d. 构造函数不确定的验证

虽然构造函数、参数名称、参数类型、参数值都确定后也不一定会直接锁定构造函数,不同构造函数的参数为父子关系,所以Spring在最后又做了一次验证。定义了一个最小的差异权重 minTypeDiffWeight,下面这段代码由于在循环体内,所以每次都会检查新的构造函数其差异权重是否更小,如果是则更新需要使用的构造函数 constructorToUse 等。

// 探测是否有不确定的构造函数存在,例如不同构造函数的参数为父子关系
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
      argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 如果他代表着当前最接近的匹配则选择作为构造函数
if (typeDiffWeight < minTypeDiffWeight) {
   // 更新
   constructorToUse = candidate;
   argsHolderToUse = argsHolder;
   argsToUse = argsHolder.arguments;
   minTypeDiffWeight = typeDiffWeight;
   ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
   if (ambiguousConstructors == null) {
      ambiguousConstructors = new LinkedHashSet<>();
      ambiguousConstructors.add(constructorToUse);
   }
   ambiguousConstructors.add(candidate);
}
e. 实例化bean

根据实例化策略,通过得到的构造函数以及构造函数参数实例化 Bean 得到 beanInstance,将其设置到 bw 中进行返回。核心代码主要就是 strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),之后文章我们会再详细介绍这里。

try {
   final InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
   Object beanInstance;

   if (System.getSecurityManager() != null) {
      final Constructor<?> ctorToUse = constructorToUse;
      final Object[] argumentsToUse = argsToUse;
      beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
            strategy.instantiate(mbd, beanName, this.beanFactory, ctorToUse, argumentsToUse),
            this.beanFactory.getAccessControlContext());
   }
   else {
      beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
   }
   // 将构建的实例加入BeanWrapper中
   bw.setBeanInstance(beanInstance);
   return bw;
}

② instantiateBean

上面讲完带参数的构造函数的实例构造,我们继续看无参的默认构造函数构造 beanInstance 返回出 beanWrapper

/**
 * 无参的实例化bean
 * Instantiate the given bean using its default constructor.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @return a BeanWrapper for the new instance
 */
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
   try {
      Object beanInstance;
      final BeanFactory parent = this;
      if (System.getSecurityManager() != null) {
         beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
               getInstantiationStrategy().instantiate(mbd, beanName, parent),
               getAccessControlContext());
      }
      else {
         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      }
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
   }
}

可以看到,无参的根本不需要像之前那样花太多精力来确认参数、匹配构造函数,只需要直接通过实例化策略进行实例化即可。

③ 实例化策略

在上面说到有参与无参的两种讨论中,最后都是通过实例化策略构造出实例。理论上,我们已经得到足以实例化的所有相关信息,完全可以使用最简单的反射方法直接反射来构造实例化对象。我们看看Spring如何实现。

有参的实例化过程:

/**
 * 有参实例化策略
 */
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
      final Constructor<?> ctor, @Nullable Object... args) {
   // 如果有需要覆盖或者动态替换的方法当然需要使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中
   // 但是如果没有需要动态改变的方法,为了方便直接反射就可以了
   if (!bd.hasMethodOverrides()) {
      if (System.getSecurityManager() != null) {
         // use own privileged to change accessibility (when security is on)
         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(ctor);
            return null;
         });
      }
      return (args != null ? BeanUtils.instantiateClass(ctor, args) : BeanUtils.instantiateClass(ctor));
   }
   else {
      return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
   }
}

无参的实例化过程:

/**
 * 无参实例化策略
 * @param bd the bean definition
 * @param beanName the name of the bean when it's created in this context.
 * The name can be {@code null} if we're autowiring a bean which doesn't
 * belong to the factory.
 * @param owner the owning BeanFactory
 * @return
 */
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
   // 如果有需要覆盖或者动态替换的方法当然需要使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中
   // 但是如果没有需要动态改变的方法,为了方便直接反射就可以了
   if (!bd.hasMethodOverrides()) {
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse == null) {
            final Class<?> clazz = bd.getBeanClass();
            if (clazz.isInterface()) {
               throw new BeanInstantiationException(clazz, "Specified class is an interface");
            }
            try {
               if (System.getSecurityManager() != null) {
                  constructorToUse = AccessController.doPrivileged(
                        (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
               }
               else {
                  constructorToUse = clazz.getDeclaredConstructor();
               }
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Throwable ex) {
               throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            }
         }
      }
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else {
      // Must generate CGLIB subclass.
      return instantiateWithMethodInjection(bd, beanName, owner);
   }
}

无论哪种,都分为 if-else 两大块。如果用户在配置文件中没有配置 replace 或者 lookup 的配置方法,那么直接使用反射方式,简单快捷。如果使用了这两个配置,再直接使用反射的方式创建实例就不妥了,因为需要将这两个配置提供的功能切入进去,所以必须保证使用动态代理的方式将两个特性所对应的逻辑的拦截增强器设置进去,这样才能保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。

对于拦截器的处理方法,AOP的相关将会在后面继续介绍。

记录bean的ObjectFactory

我们回到本部分最开始,通过上一小节的讨论,我们已经成功获取了 BeanWrapper。我们继续查看 doCreateBean() 中的逻辑:

final Object bean = instanceWrapper.getWrappedInstance();
····
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
      isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
   if (logger.isDebugEnabled()) {
      logger.debug("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
   }
   // 为避免后期循环依赖,可以在bean初始化完成之前将创建实例的ObjectFactory加入工厂
   addSingletonFactory(beanName,
         // 对bean再一次依赖引用,主要应用SmartInstantiationAware BeanPostProcessor
         // 其中我们熟知的AOP就是这样将advice动态织入bean中,若没有则直接返回bean,不做任何处理
         () -> getEarlyBeanReference(beanName, mbd, bean));
}

之前在循环依赖部分已经介绍过相关概念,earlySingletonExposure 就是为了解决循环依赖而准备的。它由三部分组成,首先是是否单例模式 mbd.isSingleton(),其次是是否允许循环依赖 this.allowCircularReferences 以及 bean 是否正在创建中 isSingletonCurrentlyInCreation(beanName) 。当这三个条件都满足时,会执行 addSingletonFactory() 方法。

/**
 * Add the given singleton factory for building the specified singleton
 * if necessary.
 * <p>To be called for eager registration of singletons, e.g. to be able to
 * resolve circular references.
 * @param beanName the name of the bean
 * @param singletonFactory the factory for the singleton object
 */
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

可以看到,在 singletonFactories 中添加了传入的 singletonFactorysingletonFactory 是我们创建的 ObjectFactory 实例,并重写了其中的 getObject() 方法:

/**
 * Obtain a reference for early access to the specified bean,
 * typically for the purpose of resolving a circular reference.
 * @param beanName the name of the bean (for error handling purposes)
 * @param mbd the merged bean definition for the bean
 * @param bean the raw bean instance
 * @return the object to expose as bean reference
 */
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() 方法中没有太多处理的逻辑,除了后处理器的调用没有别的处理工作。

属性注入

提前暴露完仅仅实现构造函数完毕的 beanObjectFactory 后,紧接着可以进行属性的填充,也就是本部分内容的第五步。属性注入是通过 populateBean 完成的,instanceWrapper 就是通过构造函数创建出的 beanWrapper

// 对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始依赖bean
populateBean(beanName, mbd, instanceWrapper);

进入函数体:

/**
 * 对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始依赖bean
 * Populate the bean instance in the given BeanWrapper with the property values
 * from the bean definition.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param bw the BeanWrapper with bean instance
 */
@SuppressWarnings("deprecation")  // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   if (bw == null) {
      if (mbd.hasPropertyValues()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // 没有可填充的属性
         return;
      }
   }

   // 给InstantiationAwareBeanPostProcessors最后一次机会在属性设置前改变bean,
   // 如:可以用来支持属性注入的类型
   boolean continueWithPropertyPopulation = true;

   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 返回值为是否继续填充bean
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }

   // 如果后处理器发出停止填充命令则终止后续的执行
   if (!continueWithPropertyPopulation) {
      return;
   }

   PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

      // Add property values based on autowire by name if applicable.
      // 根据名称自动注入
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }

      // Add property values based on autowire by type if applicable.
      // 根据类型自动注入
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }

      pvs = newPvs;
   }

   // 后处理器已经初始化
   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   // 需要依赖检查
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

   PropertyDescriptor[] filteredPds = null;
   if (hasInstAwareBpps) {
      if (pvs == null) {
         pvs = mbd.getPropertyValues();
      }
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
               if (filteredPds == null) {
                  filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
               }
               // 对所有需要依赖检查的属性进行后处理
               pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvsToUse == null) {
                  return;
               }
            }
            pvs = pvsToUse;
         }
      }
   }
   if (needsDepCheck) {
      // 依赖检查,对应depends-on属性,3.0已经弃用此属性
      if (filteredPds == null) {
         filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      }
      checkDependencies(beanName, mbd, filteredPds, pvs);
   }

   // 将属性应用到bean中
   // 将所有ProtertyValues中的属性填充至BeanWrapper中
   if (pvs != null) {
      applyPropertyValues(beanName, mbd, bw, pvs);
   }
}

又是很长的一大串!看一下代码逻辑:

(1)InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation 方法的调用,可以控制程序是否继续属性填充;
(2)根据注入类型 (byName/byType) 提取依赖的 bean,并统一存入PropertyValues 中;
(3)应用 InstantiationAwareBeanPostProcessorpostProcessPropertyValues() 方法,对属性获取完毕填充前的再次处理。典型的应用是 RequiredAnnotationBeanPostProcesser 类中对属性的验证;
(4)将所有 ProtertyValues 中的属性填充至 BeanWrapper 中。

我们着重研究依赖注入(autowireByName/autowireByType)以及属性填充部分。

① autowireByName

/**
 * 在传入的参数bw中,找出已经加载的bean,并递归实例化,进而加入到pvs中
 * Fill in any missing property values with references to
 * other beans in this factory if autowire is set to "byName".
 * @param beanName the name of the bean we're wiring up.
 * Useful for debugging messages; not used functionally.
 * @param mbd bean definition to update through autowiring
 * @param bw the BeanWrapper from which we can obtain information about the bean
 * @param pvs the PropertyValues to register wired objects with
 */
protected void autowireByName(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

   // 寻找bw中需要依赖注入的属性
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
      if (containsBean(propertyName)) {
         // 递归初始化相关的bean
         Object bean = getBean(propertyName);
         pvs.add(propertyName, bean);
         // 注册依赖
         registerDependentBean(propertyName, beanName);
         if (logger.isDebugEnabled()) {
            logger.debug("Added autowiring by name from bean name '" + beanName +
                  "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
         }
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                  "' by name: no matching bean found");
         }
      }
   }
}

除去日志等代码,逻辑较为清晰。先通过 unsatisfiedNonSimpleProperties() 找到需要填充的所有属性 name,根据传入的参数 pvs 中找出已经加载的 bean,并递归实例化,然后再加入到 pvs 中。

② autowireByType

/**
 * Abstract method defining "autowire by type" (bean properties by type) behavior.
 * <p>This is like PicoContainer default, in which there must be exactly one bean
 * of the property type in the bean factory. This makes bean factories simple to
 * configure for small namespaces, but doesn't work as well as standard Spring
 * behavior for bigger applications.
 * @param beanName the name of the bean to autowire by type
 * @param mbd the merged bean definition to update through autowiring
 * @param bw the BeanWrapper from which we can obtain information about the bean
 * @param pvs the PropertyValues to register wired objects with
 */
protected void autowireByType(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }

   Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
   // 寻找bw中需要依赖注入的属性,然后遍历这些属性去寻找类型匹配的bean
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
      try {
         PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
         // Don't try autowiring by type for type Object: never makes sense,
         // even if it technically is a unsatisfied, non-simple property.
         if (Object.class != pd.getPropertyType()) {
            // 探测指定属性的set方法
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
            // Do not allow eager init for type matching in case of a prioritized post-processor.
            boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
            DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
            // 解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowiredBeanNames中,当属性存在多个封装bean时,如:
            // @Autowired private List<A> aList; 将会找到所有匹配A类型的bean并将其注入
            Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
            if (autowiredArgument != null) {
               pvs.add(propertyName, autowiredArgument);
            }
            for (String autowiredBeanName : autowiredBeanNames) {
               // 注册依赖
               registerDependentBean(autowiredBeanName, beanName);
               if (logger.isDebugEnabled()) {
                  logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
                        propertyName + "' to bean named '" + autowiredBeanName + "'");
               }
            }
            autowiredBeanNames.clear();
         }
      }
      catch (BeansException ex) {
         throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
      }
   }
}

根据属性与根据名称两种自动注入属性第一步都是寻找 bw 中需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的 bean,其中最复杂就是寻找类型匹配的 bean。Spring中提供了对集合的类型注入的支持,如使用注解的方式:

@Autowired
private List<Test> tests;

Spring会把所有与 Test 匹配的类型找出来并注入到 tests 属性中,正因如此,所以才创建了局部遍历 autowiredBeanNames,用于存储所有依赖的 bean。如果只是对非集合类的属性注入来说,该属性没有用处。

对于寻找类型匹配的逻辑实现由 resolveDependency(desc, beanName, autowiredBeanNames, converter)

/**
 * 寻找类型匹配
 * @param descriptor the descriptor for the dependency (field/method/constructor)
 * @param requestingBeanName the name of the bean which declares the given dependency
 * @param autowiredBeanNames a Set that all names of autowired beans (used for
 * resolving the given dependency) are supposed to be added to
 * @param typeConverter the TypeConverter to use for populating arrays and collections
 * @return
 * @throws BeansException
 */
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

   descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
   if (Optional.class == descriptor.getDependencyType()) {
      // Optional类注入的特殊处理
      return createOptionalDependency(descriptor, requestingBeanName);
   }
   else if (ObjectFactory.class == descriptor.getDependencyType() ||
         ObjectProvider.class == descriptor.getDependencyType()) {
      // ObjectFactory、ObjectProvider类注入的特殊处理
      return new DependencyObjectProvider(descriptor, requestingBeanName);
   }
   else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
      // javaxInjectProviderClass类注入的特殊处理
      return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
   }
   else {
      // 通用处理逻辑
      Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
      if (result == null) {
         result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
      }
      return result;
   }
}

Spring在寻找匹配类型时,对于 Optional 类型、ObjectFactory 类型、ObjectProvider 类型和 javaxInjectProviderClass 类型依赖进行单独的处理。而正常类型的依赖委托 doResolveDependency() 方法去完成。

/**
 * 正常类型的依赖处理
 * @param descriptor
 * @param beanName
 * @param autowiredBeanNames
 * @param typeConverter
 * @return
 * @throws BeansException
 */
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

   InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
   try {
      Object shortcut = descriptor.resolveShortcut(this);
      if (shortcut != null) {
         return shortcut;
      }

      Class<?> type = descriptor.getDependencyType();
      // 用于支持Spring中新增的注解@Value
      Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
      if (value != null) {
         if (value instanceof String) {
            String strVal = resolveEmbeddedValue((String) value);
            BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
            value = evaluateBeanDefinitionString(strVal, bd);
         }
         TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
         return (descriptor.getField() != null ?
               converter.convertIfNecessary(value, type, descriptor.getField()) :
               converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
      }

      // 如果解析器没有成功解析,则需要考虑各种情况
      Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
      if (multipleBeans != null) {
         return multipleBeans;
      }

      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (matchingBeans.isEmpty()) {
         // 如果找到的匹配类型的bean为空,同时autowire的require属性为true,需要抛出异常
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         return null;
      }

      String autowiredBeanName;
      Object instanceCandidate;

      if (matchingBeans.size() > 1) {
         // 当集合或者数组中类型匹配到的bean不止一个
         autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
         
         if (autowiredBeanName == null) {
            if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
               return descriptor.resolveNotUnique(type, matchingBeans);
            }
            else {
               // In case of an optional Collection/Map, silently ignore a non-unique case:
               // possibly it was meant to be an empty collection of multiple regular beans
               // (before 4.3 in particular when we didn't even look for collection beans).
               return null;
            }
         }
         instanceCandidate = matchingBeans.get(autowiredBeanName);
      }
      else {
         // 已经确定只有一个匹配项,集合或数组中只有一个bean
         Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
         autowiredBeanName = entry.getKey(); // beanName
         instanceCandidate = entry.getValue(); // bean
      }

      if (autowiredBeanNames != null) {
         autowiredBeanNames.add(autowiredBeanName);
      }
      if (instanceCandidate instanceof Class) {
         instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }
      Object result = instanceCandidate;
      
      // 再次check解析到的依赖bean是否有以及类型是否正确
      if (result instanceof NullBean) {
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         result = null;
      }
      if (!ClassUtils.isAssignableValue(type, result)) {
         throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
      }
      return result;
   }
   finally {
      ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
   }
}

寻找类型的匹配时,首先尝试使用解析器进行解析。如果解析器没有解析成功,那么可能是使用默认的解析器没有做出任何处理,或者是使用了自定义的解析器,但是对于数组、集合等类型来说并不在解析范围之内,所以针对他们需要再次对不同的类型进行不同的处理。具体是委托 resolveMultipleBeans() 方法去处理:

/**
 * 处理类型为数组、集合类型的
 * @param descriptor
 * @param beanName
 * @param autowiredBeanNames
 * @param typeConverter
 * @return
 */
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

   Class<?> type = descriptor.getDependencyType();
   // 如果解析器没有成功解析,则需要考虑各种情况
   // 属性是数组类型
   if (type.isArray()) {
      // 获取数组中元素类型
      Class<?> componentType = type.getComponentType();

      ResolvableType resolvableType = descriptor.getResolvableType();
      Class<?> resolvedArrayType = resolvableType.resolve();
      if (resolvedArrayType != null && resolvedArrayType != type) {
         type = resolvedArrayType;
         componentType = resolvableType.getComponentType().resolve();
      }
      if (componentType == null) {
         return null;
      }
      // 根据属性类型找到beanFactory中所有类型的匹配bean,
      // 返回值的构成为:key=匹配的beanName,value=beanName对应的实例化后的bean(通过getBean(beanName)返回)
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
            new MultiElementDescriptor(descriptor));
      if (matchingBeans.isEmpty()) {
         return null;
      }
      if (autowiredBeanNames != null) {
         autowiredBeanNames.addAll(matchingBeans.keySet());
      }
      // 通过转换器将bean的值转换为对应的type类型
      TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
      Object result = converter.convertIfNecessary(matchingBeans.values(), type);
      if (getDependencyComparator() != null && result instanceof Object[]) {
         Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
      }
      return result;
   }
   // 属性是Collection类型
   else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
      // 获取元素类型
      Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
      if (elementType == null) {
         return null;
      }
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
            new MultiElementDescriptor(descriptor));
      if (matchingBeans.isEmpty()) {
         return null;
      }
      if (autowiredBeanNames != null) {
         autowiredBeanNames.addAll(matchingBeans.keySet());
      }
      TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
      Object result = converter.convertIfNecessary(matchingBeans.values(), type);
      if (getDependencyComparator() != null && result instanceof List) {
         ((List<?>) result).sort(adaptDependencyComparator(matchingBeans));
      }
      return result;
   }
   // 属性是Map类型
   else if (Map.class == type) {
      ResolvableType mapType = descriptor.getResolvableType().asMap();
      // 获取key的类型
      Class<?> keyType = mapType.resolveGeneric(0);
      if (String.class != keyType) {
         return null;
      }
      // 获取value类型
      Class<?> valueType = mapType.resolveGeneric(1);
      if (valueType == null) {
         return null;
      }
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
            new MultiElementDescriptor(descriptor));
      if (matchingBeans.isEmpty()) {
         return null;
      }
      if (autowiredBeanNames != null) {
         autowiredBeanNames.addAll(matchingBeans.keySet());
      }
      return matchingBeans;
   }
   else {
      return null;
   }
}

函数主要对数组、集合类型进行处理,主要都是根据属性类型找到 beanFactory 中所有类型的匹配 bean,将 key 为匹配的 beanNamevaluebeanName 对应的实例化后的 beanmap

③ applyPropertyValues

经过①和②,我们已经获取到了需要注入的属性,最后这些属性的保存形式为 PropertyValues,还没有应用到已经实例化的 bean 中,所以下一步需要利用 applyPropertyValues(beanName, mbd, bw, pvs) 方法将 PropertyValues 中的属性设置到 bean 中:

/**
 * 将所有ProtertyValues中的属性填充至BeanWrapper中
 * Apply the given property values, resolving any runtime references
 * to other beans in this bean factory. Must use deep copy, so we
 * don't permanently modify this property.
 * @param beanName the bean name passed for better exception information
 * @param mbd the merged bean definition
 * @param bw the BeanWrapper wrapping the target object
 * @param pvs the new property values
 */
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
   if (pvs.isEmpty()) {
      return;
   }

   if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
      ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
   }

   MutablePropertyValues mpvs = null;
   List<PropertyValue> original; // 保存PropertyValue数组

   // 如果PropertyValues是MutablePropertyValues类型,那么尝试直接将PropertyValues设置到BeanWrapper中
   // 如果设置到BeanWrapper失败和或者不是MutablePropertyValues类型,都将PropertyValues转换成PropertyValue数组放到original
   // 然后再用original构造出MutablePropertyValues设置到BeanWrapper中
   if (pvs instanceof MutablePropertyValues) {
      mpvs = (MutablePropertyValues) pvs;
      // 如果mpvs中的值已经被转换为对应的类型那么可以直接设置到beanwapper中
      if (mpvs.isConverted()) {
         // Shortcut: use the pre-converted values as-is.
         try {
            bw.setPropertyValues(mpvs);
            return;
         }
         catch (BeansException ex) {
            throw new BeanCreationException(
                  mbd.getResourceDescription(), beanName, "Error setting property values", ex);
         }
      }
      original = mpvs.getPropertyValueList();
   }
   else {
      // 如果pvs并不是使用MutablePropertyValues封装的类型,那么直接使用原始的属性获取方法
      original = Arrays.asList(pvs.getPropertyValues());
   }

   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }
   // 获取对应的解析器
   BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

   // Create a deep copy, resolving any references for values.
   List<PropertyValue> deepCopy = new ArrayList<>(original.size());
   boolean resolveNecessary = false;

   // 遍历属性,将属性转换为对应类的对应属性的类型
   for (PropertyValue pv : original) {
      if (pv.isConverted()) {
         deepCopy.add(pv);
      }
      else {
         String propertyName = pv.getName();
         Object originalValue = pv.getValue();
         Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
         Object convertedValue = resolvedValue;
         boolean convertible = bw.isWritableProperty(propertyName) &&
               !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
         if (convertible) {
            convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
         }
         // Possibly store converted value in merged bean definition,
         // in order to avoid re-conversion for every created bean instance.
         if (resolvedValue == originalValue) {
            if (convertible) {
               pv.setConvertedValue(convertedValue);
            }
            deepCopy.add(pv);
         }
         else if (convertible && originalValue instanceof TypedStringValue &&
               !((TypedStringValue) originalValue).isDynamic() &&
               !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
            pv.setConvertedValue(convertedValue);
            deepCopy.add(pv);
         }
         else {
            resolveNecessary = true;
            deepCopy.add(new PropertyValue(pv, convertedValue));
         }
      }
   }
   if (mpvs != null && !resolveNecessary) {
      mpvs.setConverted();
   }

   // Set our (possibly massaged) deep copy.
   try {
      bw.setPropertyValues(new MutablePropertyValues(deepCopy));
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
   }
}

初始化bean

bean 属性填充完需要进行 bean 的初始化,在配置文件中可以通过 init-method 这个属性配置,在 bean 实例化前调用 init-method 指定的方法来根据用户业务进行相应的实例化。我们来看一下执行用户配置的初始化方法的方法在哪里执行。之前Spring已经执行了 bean 的实例化,紧接着又做了属性填充,随后调用了:

exposedObject = initializeBean(beanName, exposedObject, mbd)

而用户配置的初始化就是在这里完成的。

/**
 * 初始化bean-->用户配置的init-method
 * Initialize the given bean instance, applying factory callbacks
 * as well as init methods and bean post processors.
 * <p>Called from {@link #createBean} for traditionally defined beans,
 * and from {@link #initializeBean} for existing bean instances.
 * @param beanName the bean name in the factory (for debugging purposes)
 * @param bean the new bean instance we may need to initialize
 * @param mbd the bean definition that the bean was created with
 * (can also be {@code null}, if given an existing bean instance)
 * @return the initialized bean instance (potentially wrapped)
 * @see BeanNameAware
 * @see BeanClassLoaderAware
 * @see BeanFactoryAware
 * @see #applyBeanPostProcessorsBeforeInitialization
 * @see #invokeInitMethods
 * @see #applyBeanPostProcessorsAfterInitialization
 */
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      // 对特殊的bean的处理:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      // 应用后处理器
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      // 激活用户自定义的init方法
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null || !mbd.isSynthetic()) {
      // 后处理应用
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

虽然该函数主要目的是调用用户设置的初始化方法,但是仍然还有一些其他工作需要完成。

① 激活Aware方法

先了解一下 Aware 的使用。Spring中提供了一些 Aware 接口,比如BeanFactoryAwareApplicationContextAwareResourceLoaderAwareServletContextAware 等,实现这些 Aware 接口的 bean 在被初始化后,可以取得一些相对应的资源,例如实现 BeanFactoryAwarebean 在初始化之后,Spring容器将会注入 BeanFactory 实例,而实现 ApplicationContextAwarebean,在 bean 被初始化后,将会被注入 ApplicationContext 实例等。我们先通过示例方法了解下 Aware 的使用。

spring-mytest 模块中新建普通实体类 Hello

public class Hello {
   
   public void say() {
      System.out.println("hello");
   }
}

定义 beanFactoryAware类型的 bean

public class TestAware implements BeanFactoryAware {
   
   private BeanFactory beanFactory;
   
   @Override
   public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
      this.beanFactory = beanFactory;
   }
   
   public void testAware() {
      Hello hello = (Hello) this.beanFactory.getBean("hello");
      hello.say();
   }
}

编写配置文件 awareTest.xml

<?xml version='1.0' encoding='UTF-8' ?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="hello" class="guo.ping.ioc.aware.Hello" />
   <bean id="test" class="guo.ping.ioc.aware.TestAware" />
</beans>

编写测试类:

public class AwareTest {

   @Test
   public void sing() {
      ApplicationContext context = new ClassPathXmlApplicationContext("awareTest.xml");
      TestAware testAware = (TestAware) context.getBean("test");
      testAware.testAware();
   }
}

测试结果:

测试结果

测试代码中,TestAware 实现了 BeanFactoryAware 接口,在名为 testbean 实例化的时候,该 bean 能够自动被注入 BeanFactory 的实例,从而能够在其 testAware() 方法中通过 BeanFactory 的实例进一步获取到名为 hellobean。为了做到这一点,Spring实现的本质就是通过 invokeAwareMethods(beanName, bean) 方法,分别对三种 Aware 调用了 setter 方法。

private void invokeAwareMethods(final String beanName, final Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
         ClassLoader bcl = getBeanClassLoader();
         if (bcl != null) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
         }
      }
      if (bean instanceof BeanFactoryAware) {
         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
   }
}

② 处理器的应用

BeanPostPrecessor ——后处理器,这是Spring开放式架构的一个必不可少的亮点,给用户充足的权限去更改或者扩展Spring,而除了 BeanPostProcessor 外还有很多其他的 PostProcessor,当然大部分都以此为基础,继承自 BeanPostProcessorBeanPostProcessor 在调用用户自定义初始化方法或者调用自定义初始化方法分别会调用 BeanPostProcessorpostProcessBeforeInitializationpostProcessAfterinitialization 方法,使用户可以根据自己的业务需求就行相应的处理。

我们同样研究一下初始化前和初始化后后处理器应用代码

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
······
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

中怎样实现的:

/**
 * 初始化前应用BeanPostProcessors后处理器
 * @param existingBean the new bean instance
 * @param beanName the name of the bean
 * @return
 * @throws BeansException
 */
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {

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


/**
 * 初始化后应用BeanPostProcessors后处理器
 * @param existingBean the new bean instance FactoryBean的getObject获得的对象
 * @param beanName the name of the bean 处理后的bean name
 * @return
 * @throws BeansException
 */
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

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

③ 激活用户自定义init方法

用户定制的初始化方法除了我们熟知的使用配置 init-method 外,还可以通过让自定义的 bean 实现 InitializingBean 接口,并在 afterPropertiesSet 中实现自己的初始化业务逻辑。

init-methodafterPropertiesSet 都是在初始化 bean 时执行,执行顺序是 afterPropertiesSet 先执行,而 init-method 后执行。

我们具体来看看这两个步骤的初始化调用:

/**
 * 激活用户自定义初始化方法
 * Give a bean a chance to react now all its properties are set,
 * and a chance to know about its owning bean factory (this object).
 * This means checking whether the bean implements InitializingBean or defines
 * a custom init method, and invoking the necessary callback(s) if it does.
 * @param beanName the bean name in the factory (for debugging purposes)
 * @param bean the new bean instance we may need to initialize
 * @param mbd the merged bean definition that the bean was created with
 * (can also be {@code null}, if given an existing bean instance)
 * @throws Throwable if thrown by init methods or by the invocation process
 * @see #invokeCustomInitMethod
 */
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
      throws Throwable {

   // 首先检查bean是否是InitializingBean实例,是的话需要先调用afterPropertiesSet方法
   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
      if (logger.isDebugEnabled()) {
         logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
      }
      if (System.getSecurityManager() != null) {
         try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
               ((InitializingBean) bean).afterPropertiesSet();
               return null;
            }, getAccessControlContext());
         }
         catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }
      else {
         // 属性初始化后的处理
         ((InitializingBean) bean).afterPropertiesSet();
      }
   }

   if (mbd != null && bean.getClass() != NullBean.class) {
      String initMethodName = mbd.getInitMethodName();
      if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
         // 调用自定义初始化方法
         invokeCustomInitMethod(beanName, bean, mbd);
      }
   }
}

注册DisposableBean

我们来到这一部分**(do)创建bean**的最后一步,如果XML配置了 destory-method,这里需要注册以便于销毁 bean 的时候调用。Spring中不仅提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口。除了 destroy-method 之外,还可以注册后处理器 DestructionAwareBeanPostProcessor 来统一处理 bean 的销毁方法:

/**
 * 注册DisposableBean,销毁方法的扩展入口
 * Add the given bean to the list of disposable beans in this factory,
 * registering its DisposableBean interface and/or the given destroy method
 * to be called on factory shutdown (if applicable). Only applies to singletons.
 * @param beanName the name of the bean
 * @param bean the bean instance
 * @param mbd the bean definition for the bean
 * @see RootBeanDefinition#isSingleton
 * @see RootBeanDefinition#getDependsOn
 * @see #registerDisposableBean
 * @see #registerDependentBean
 */
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.
         registerDisposableBean(beanName,
               new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
      }
      else {
         // A bean with a custom 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));
      }
   }
}

IX. 总结

文章短短续续又将近写了20天,也是因为太长,中间还有一些事情耽搁,导致越拖越记不清,不过总算完成。明显感觉 bean 的加载这一部分太深奥了,能坚持看下来很不错了吧,能懂多少只能看自己悟性了,自己希望没事多翻翻吧。

这样,从第一篇文章的例子整个流程就走完了,配置文件的读取解析、bean 的加载,之前我们用的是 XmlBeanFactory 这个 BeanFactory,接下来我们要去接触一下常用的 ApplicationContext 了。

学如逆水行舟,不进则退….

参考列表

猜你喜欢

转载自blog.csdn.net/bskfnvjtlyzmv867/article/details/82859993