3、Spring源码-bean的加载

436 阅读49分钟

更多文章请观看:[www.shangsw.com]

一 bean的加载

我们在示例中,对bean的调用方式为:

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

我们先快速体验一下Spring中代码是如何实现的:

/**
* 通过beanName获取Bean实例
* @param name beanName
* @return 对应的Bean实例
* @throws BeansException Bean异常
*/
@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}
/**
* 返回一个实例, 这个实例可能是共享的也可能是独享的
* @param name beanName
* @param requiredType 类型。可以为null
* @param args 构造函数的参数。可以为null
* @param typeCheckOnly 是否需要进行类型检查。非实际使用
* @param <T> 类型
* @return 实例
* @throws BeansException Bean异常
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
   String beanName = transformedBeanName(name);//提取对应的beanName
   Object bean;

   /*
    * 检查缓存中或者实例工厂中是否有对应的实例
    * 为什么首先会使用这段代码?
    * 因为在创建单例bean的时候会存在依赖注入的情况, 而在创建依赖的时候为了避免循环依赖,
    * Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光,
    * 也就是将ObjectFactory加入到缓存中, 一旦下个bean创建时候需要依赖上个bean则直接使用ObjectFactory
    */
   Object sharedInstance = getSingleton(beanName);//直接尝试从缓存获取或者singletonFactories中的ObjectFactory中获取
   if (sharedInstance != null && args == null) {//从二级或者三级缓存中获取到了对象并且构造参数为空
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {//如果这个对象在一级缓存中
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         } else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }

      //返回对应的实例, 有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   } else {//不存在
      /*
       * 只有在单例的情况下才会尝试解决循环依赖, 原型模式情况下, 如果存在
       * A中有B的属性, B中也有A的属性, 那么当依赖注入的时候, 就会产生当A还未创建完成的时候因为
       * 对于B的创建再次返回创建A, 造成循环依赖, 也就是下面的情况
       */
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      //如果beanDefinitionMap中也就是所有已经加载的的类中不包括beanName则尝试从parentBeanFactory中检测 Start
      BeanFactory parentBeanFactory = getParentBeanFactory();//父类的beanFactory
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//存在父beanFactory并且beanDefinitionMap中不存在该bean
         String nameToLookup = originalBeanName(name);//将name添加前缀&
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);//寻找父类的实例
         } else if (args != null) {
            return (T) parentBeanFactory.getBean(nameToLookup, args);//寻找父类的实例
         } else if (requiredType != null) {
            return parentBeanFactory.getBean(nameToLookup, requiredType);//寻找父类的实例
         } else {
            return (T) parentBeanFactory.getBean(nameToLookup);//寻找父类的实例
         }
      }
      //如果beanDefinitionMap中也就是所有已经加载的的类中不包括beanName则尝试从parentBeanFactory中检测 End

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

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

         //若存在依赖, 则需要递归实例化依赖的bean Start
         String[] dependsOn = mbd.getDependsOn();
         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);
               }
            }
         }
         //若存在依赖, 则需要递归实例化依赖的bean End

         //实例化依赖的bean后便可以实例化mbd本身了
         if (mbd.isSingleton()) {//singleton模式的创建
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               } catch (BeansException ex) {
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         } else if (mbd.isPrototype()) {//protype模式创建
            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();
            if (!StringUtils.hasLength(scopeName)) {
               throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
            }
            Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  } finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               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;
      }
   }

   //检查需要的类型是否符合bean的实际类型 Start
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      } catch (TypeMismatchException ex) {
         if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   //检查需要的类型是否符合bean的实际类型 End
   return (T) bean;
}

从代码来看bean的加载经历了一个相当复杂的过程,其中涉及各种各样的考虑。而我们此时可以粗略了解Spring加载bean的过程:

  • 转换对应的beanName

其实传入的name并就是beanName,这里传入的参数可能是别名,也可能是FactoryBean,所以需要进行一系列的解析,解析的内容包括:

  • 去除FactoryBean的修饰,也就是如果name="&aa",那么会首先去除&而使name="aa"。
  • 取指定alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B;若别名A指向别名B,别名B又指向名称为C的bean则返回C
  • 尝试从缓存中加载单例

单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。当然,这里只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会将创建的bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory

  • bean的实例化

如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。注意,缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean

  • 原型模式的依赖检查

只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完成的时候因为对B的创建再次返回创建A,造成循环依赖。也就是:isPrototypeCurrentlyInCreation(beanName) 判断为true。

  • 检测parentBeanFactory

从代码上看,如果缓存没有数据的话直接转到父类工厂上去加载了。判断条件:parentBeanFactory != null && !containsBeanDefinition(beanName), parentBeanFactory != null。parentBeanFactory如果为空,就没什么可说的。但是!containsBeanDefinition(beanName)就比较重要了,它是检测如果当前加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试下,然后再递归的调用getBean方法。

  • 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition

因为从XML配置文件中读取到的Bean信息都存储在GenericBeanDefinition中的,但是所有的Bean后续处理都是针对RootBeanDefinition的,所以这里需要进行一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性

  • 寻找依赖

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

  • 针对不同scope进行bean的创建

在Spring中存在着不同的scope,其中默认的是singleton,但是还有其他的配置诸如prototype、request之类的。在这个步骤中,Spring会根据不同的配置进行不同的初始化策略

  • 类型转换

程序到这里返回bean后已经基本结束了,通常对该方法调用参数requiredType是为空的,但是可能会存在这种情况,返回bean其实是个String,但是requiredType却传入Integer类型,那么这个步骤就会起作用。它的功能是将返回的bean转换为requiredType所指定的类型。

经过上面步骤后bean的加载就结束了,其中最重要的就是第8步,针对不同的scope进行bean的创建。

1.1 FactoryBean的使用

FactoryBean是一个工厂接口,与BeanFactory不一样,BeanFactory是一个容器类。FactoryBean可以生成某一个类型Bean实例,它最大的作用是:可以让我们自定义Bean的创建过程。FactoryBean的代码如下:

public interface FactoryBean<T> {
   String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

   @Nullable
   T getObject() throws Exception;

   @Nullable
   Class<?> getObjectType();

   default boolean isSingleton() {
      return true;
   }
}
  • T getObject():返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单例缓存池中
  • boolean isSingleton():返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
  • Class getObjectType():返回FactoryBean创建的bean类型

当配置文件中的的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法返回的对象,相当于FactoryBean#getObject()代理了getBean()方法

例如,如果使用传统方式配置下面Car的时,Car的每个属性分别对应一个元素标签:

public class Car {
    /** 最大的速度 */
    private int maxSpeed;

    /** 品牌 */
    private String brand;

    /** 价格 */
    private double price;

    //get/set方法
}

如果使用FactoryBean的方式实现就会灵活一些,下面通过逗号分隔的方式一次性为Car的所有属性指定配置值:

public class CarFactoryBean implements FactoryBean<Car> {
    /** 信息, 使用逗号分隔。{品牌},{速度},{价格} */
    private String carInfo;

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

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

    //get/set/constructor
}

有了CarFactoryBean后,就可以在配置文件中使用下面这种自定义的配置方式了:

<bean id="car" class="com.bianjf.factory.CarFactoryBean">
    <constructor-arg index="0" value="超级跑车,400,20000000"/>
</bean>

当调用getBean("car")时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean#getObject()方法返回。如果希望获取CarFactoryBean的实例,则需要使用getBean(beanName)方法时在beanName前显示加上“&”前缀,例如getBean("&car")

1.2 缓存中获取单例bean

单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然,这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactories中加载

因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上一个bean,则直接使用ObjectFactory

/**
* 通过beanNanme获取单例对象
* @param beanName beanName
* @return 可能是二级缓存(没有属性注入)单例对象, 也可能是一级缓存(完整的单例)单例对象, 也可能是对象工厂创建的对象(即直接创建没走缓存), 也可能是null
*/
@Override
@Nullable
public Object getSingleton(String beanName) {
   return getSingleton(beanName, true);
}
/**
* 返回指定的beanName的单例对象。
* 首先检查是否存在这个单例对象, 如果不存在, 则通过参数控制(allowEarlyReference)是否允许创建早期的引用对象(没有属性注入)
* @param beanName            beanName
* @param allowEarlyReference 是否允许创建早期的对象(没有属性注入)
* @return 单例对象
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   Object singletonObject = this.singletonObjects.get(beanName);//获取完整的单例对象(一级缓存)

   //一级缓存没有获取到单例对象并且这个对象正在创建中情况(singletonsCurrentlyInCreation缓存beanName) Start
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      singletonObject = this.earlySingletonObjects.get(beanName);//获取早期的单例对象(没有属性注入, 即二级缓存)

      //没有获取到早期的单例对象(二级缓存)并且允许创建早期的引用 Start
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {//全局变量Map, 存在并发访问问题, 写入需要加锁
            singletonObject = this.singletonObjects.get(beanName);//双重锁检查保证单例的唯一性
            if (singletonObject == null) {//不存在
               singletonObject = this.earlySingletonObjects.get(beanName);//获取早期的单例对象
               if (singletonObject == null) {//早期的单例对象也不存在
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);//获取单例的对象工厂
                  if (singletonFactory != null) {
                     singletonObject = singletonFactory.getObject();//单例对象
                     this.earlySingletonObjects.put(beanName, singletonObject);//存放早期的单例对象(没有属性注入)
                     this.singletonFactories.remove(beanName);//从对象工厂的缓存中删除
                  }
               }
            }
         }
      }
      //没有获取到早期的单例对象(二级缓存)并且允许创建早期的引用 End
   }
   //一级缓存没有获取到单例对象并且这个对象正在创建中情况(singletonsCurrentlyInCreation缓存beanName) End
   return singletonObject;//存在直接返回
}

这个方法首先尝试从singletonObjects(一级缓存)里面获取实例,如果获取不到再从earlySingletonObjects(二级缓存)里面获取,如果还获取不到,再尝试从singletonFactories(三级缓存)里面获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject来创建bean,并放到earlySingletonObjects里面去,并且从singletonFactories里面remove掉这个ObjectFactory,而对于后续所有内存操作都只为了循环依赖检测时候使用,也就是在allowEarlyRefrence为true的情况下才会使用。

这里涉及用于存储bean的不用map,如下:

  • singletonObjects:一级缓存,用于保存beanName和创建完整的单例bean之间的关系。 beanName -> bean instance
  • earlySingletonObjects:二级缓存,这个也是保存beanName和创建bean实例之间的关系,与singletonObjects不同之处在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用,并且这个bean其实是不完整的bean实例,这个时候的bean实例并没有属性注入
  • singletonFactories:三级缓存,用于保存beanName和bean的工厂之间的关系。beanName -> ObjectFactory
  • registeredSingletons:用来保存当前所有已注册的bean

1.3 从bean的实例中获取对象

在getBean方法中,getObjectForBeanInstance是个高频使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean。总之,我们得到bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前bean是否是FactoryBean类型的bean。如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值

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

/**
* 获取我们最终想要的bean。无论是从缓存中获取到的bean还是通过不同scope策略加载的bean都只是最原始的bean状态(没有属性注入),
* 并不是我们需要的bean。getgetObjectForBeanInstance就是获取我们最终想要的bean
* @param beanInstance 缓存中获取到的bean实例
* @param name 传入的名字。可能是beanName, 也可能是factoryBeanName(即beanName添加了&前缀)
* @param beanName beanName
* @param mbd 根的bean定义
* @return bean
*/
protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   //如果是FactoryBean, 并且直接获取FactoryBean的实例, 而不是FactoryBean的getObject的bean实例 Start
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      if (beanInstance instanceof NullBean) {//如果是空的bean, 则直接返回
         return beanInstance;
      }
      if (!(beanInstance instanceof FactoryBean)) {//beanInstance如果不是FactoryBean, 则验证不通过
         throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
      }

      if (mbd != null) {
         mbd.isFactoryBean = true;
      }
      return beanInstance;//直接返回传入的bean实例
   }
   //如果是FactoryBean, 并且直接获取FactoryBean的实例, 而不是FactoryBean的getObject的bean实例 End

   //这个bean可能是正常的bean也可能是FactoryBean, 如果不是FactoryBean, 则直接返回 Start
   if (!(beanInstance instanceof FactoryBean)) {
      return beanInstance;
   }
   //这个bean可能是正常的bean也可能是FactoryBean, 如果不是FactoryBean, 则直接返回 End

   //是FactoryBean, 但是beanName是不加&的(即从FactoryBean中获取bean实例) Start
   Object object = null;
   if (mbd != null) {
      mbd.isFactoryBean = true;
   } else {
      //尝试从缓存中加载Bean(存在则直接返回)
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {//不存在则从FactoryBean中获取
      //这里已经明确知道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());

      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
   //是FactoryBean, 但是beanName是不加&的(即从FactoryBean中获取bean实例) End
}

getObjectForBeanInstance主要做的工作有:

  • 对FactoryBean正确性校验
  • 对非FactoryBean不做任何处理
  • 对bean进行转换
  • 将从Factory中解析bean的工作委托给getObjectFromFactoryBean

getObjectFromFactoryBean()方法的代码如下:

/**
* 从给定的FactoryBean中获取单例对象
* @param factory FactoryBean
* @param beanName beanName
* @param shouldPostProcess 是否应该后期处理
* @return 单例对象
*/
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   if (factory.isSingleton() && containsSingleton(beanName)) {//判断是否是单例并且一级缓存(singletonObjects)中存在这个对象
      synchronized (getSingletonMutex()) {//锁住一级缓存(singletonObjects)
         Object object = this.factoryBeanObjectCache.get(beanName);//获取单例对象
         if (object == null) {//不存在这个单例对象
            object = doGetObjectFromFactoryBean(factory, beanName);//从FactoryBean中获取(可能存在循环依赖的情况)
            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);//从缓存中获取(避免循环引用)
            if (alreadyThere != null) {
               object = alreadyThere;
            } else {
               if (shouldPostProcess) {
                  if (isSingletonCurrentlyInCreation(beanName)) {//如果该对象还是在创建的过程中, 则这个对象没有创建完直接返回
                     return object;
                  }

                  beforeSingletonCreation(beanName);//创建之前校验

                  try {
                     object = postProcessObjectFromFactoryBean(object, beanName);//空逻辑, 直接返回传入的object, 留给子类实现
                  } catch (Throwable ex) {
                     throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", ex);
                  } finally {
                     afterSingletonCreation(beanName);
                  }
               }

               if (containsSingleton(beanName)) {//存放缓存
                  this.factoryBeanObjectCache.put(beanName, object);
               }
            }
         }
         return object;
      }
   } else {//一级缓存不存在这个对象
      Object object = doGetObjectFromFactoryBean(factory, beanName);//从对应的FactoryObject获取对象
      if (shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);//后续处理逻辑
         } catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;//不做任何操作, 返回
   }
}

这个方法并没有看到FactoryBean#getObject(),这个方法只做了一件事情,就是返回的bean如果是单例的,那就必须要保证全局唯一,同时也因为是单例,所以使用缓存来提高性能,也就是说已经加载过就要记录下来以便于下次复用,否则的话就直接获取了。

在doGetObjectFromFactoryBean()方法中,我们看到了从工厂获取的bean,也就是object = factory.getBean():

/**
* 从FactoryBean中获取对象的实例
* @param factory FactoryBean
* @param beanName beanName
* @return 指定的对象
* @throws BeanCreationException 创建Bean异常
*/
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, 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 {//从对应的FactoryBean中获取对象实例
         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);
   }

   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;
}

如果bean声明为FactoryBean类型,则当提取bean时提取的并不是FactoryBean,而是FactoryBean中对应的getObject方法返回的bean,而doGetObjectFromFactoryBean正是实现这个功能的

我们再返回到getObjectFromFactoryBean方法:

/**
* 从给定的FactoryBean中获取单例对象
* @param factory FactoryBean
* @param beanName beanName
* @param shouldPostProcess 是否应该后期处理
* @return 单例对象
*/
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   if (factory.isSingleton() && containsSingleton(beanName)) {//判断是否是单例并且一级缓存(singletonObjects)中存在这个对象
      ...

   } else {//一级缓存不存在这个对象
      Object object = doGetObjectFromFactoryBean(factory, beanName);//从对应的FactoryObject获取对象
      if (shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);//后续处理逻辑
         } catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;//不做任何操作, 返回
   }
}

方法在doGetObjectFromFactoryBean后并没有直接返回object,而是做了些后处理的操作。跟踪到AbstractAutowireCapableBeanFactory类的postProcessObjectFromFactoryBean方法:

/**
* 处理后续的逻辑。
* @param object 单例对象
* @param beanName beanName
* @return 处理后的对象
*/
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
   return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
/**
* 实例化后的后处理器应用
* @param existingBean 已经存在的bean
* @param beanName     beanName
* @return 可能被修改过的bean对象
* @throws BeansException 异常
*/
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
   Object result = existingBean;

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

这里我们先不做详细的介绍,因为后处理跟AOP有联动,在后续的AOP中进行介绍。这里需要注意:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理

1.4 获取单例

之前我们了解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean就需要从头开始bean的加载过程了,而Spring中使用getSingleton的重载方法实现bean的加载过程:

/**
* 通过给定的beanName创建一个单例的Bean对象
* @param beanName beanName
* @param singletonFactory 单例的bean对象工厂
* @return 注册的单例对象
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   synchronized (this.singletonObjects) {//全局变量需要加锁
      Object singletonObject = this.singletonObjects.get(beanName);//先从单例对象(一级缓存)中获取

      //一级缓存不存在这个对象 Start
      if (singletonObject == null) {
         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 + "'");
         }

         beforeSingletonCreation(beanName);//创建之前检查
         boolean newSingleton = false;//标识这个对象是否是new出来的
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }

         try {
            singletonObject = singletonFactory.getObject();//从工厂对象中创建
            newSingleton = true;//将标识改为true
         } catch (IllegalStateException ex) {
            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;
            }
            afterSingletonCreation(beanName);//创建之后校验
         }

         if (newSingleton) {//如果这个对象是new出来的, 将对象添加到缓存中
            addSingleton(beanName, singletonObject);//将对象添加到一级缓存中
         }
      }
      //一级缓存不存在这个对象 End
      return singletonObject;
   }
}

上述代码中其实是使用了回调方法,使得程序可以在单例创建的前后做一些准备以及处理操作,而真正的获取单例bean的方法其实并不是在此方法中实现的,其实现逻辑是在ObjectFactory类型的实例singletonFactory中实现的,而这些准备及处理操作包括如下内容:

(1) 检查缓存是否已经加载过

(2) 若没有加载,则记录beanName的正在加载状态

(3) 加载单例前记录加载状态

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

/**
* 创建前校验处理.
* 如果检查这个beanName没有排除正在创建中
* @param beanName beanName
*/
protected void beforeSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}

(4) 通过调用参数传入的ObjectFactory的个体Object方法实例化bean

(5) 加载单例后的处理方法调用

同步骤(3) 的记录加载状态相似,当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录:

/**
* 创建bean之后的一些逻辑:
* 如果这个时候inCreationCheckExclusions不存在
* @param beanName beanName
*/
protected void afterSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
   }
}

(6) 将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态

/**
* 将单例对象添加到缓存中, 并删除早期的缓存对象
* @param beanName beanName
* @param singletonObject 单例对象
*/
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);//缓存单例对象的beanName
   }
}

(7) 返回处理结果

bean的加载逻辑其实是传入的ObjectFactory类型的参数singletonFactory中定义的,如下:

sharedInstance = getSingleton(beanName, () -> {
   try {
      return createBean(beanName, mbd, args);
   } catch (BeansException ex) {
      destroySingleton(beanName);
      throw ex;
   }
});

ObjectFactory的核心部分其实只是调用了createBean的方法,所以createBean是核心逻辑。

1.5 准备创建bean

createBean的代码如下:

/**
* 这个类的核心方法: 创建bean实例, 并填充这个bean实例(填充属性), 执行post处理
* @param beanName beaName
* @param mbd      合并了所有属性的RootBeanDefinition
* @param args     构造函数的参数
* @return ObjectFactory
* @throws BeanCreationException bean创建异常
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
   }

   RootBeanDefinition mbdToUse = mbd;

   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);//根据设置的class属性或者根据className来解析Class
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);//将解析的class存储起来
   }

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

   //给BeanPostProcessors一个机会来返回代理来替代真正的实例 Start
   try {
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   } catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }
   //给BeanPostProcessors一个机会来返回代理来替代真正的实例 End

   //创建并返回bean实例 Start
   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      throw ex;
   } catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
   //创建并返回bean实例 End
}

从代码总可以看出函数完成的具体步骤及功能:

  • 根据设置的class属性或者根据className来解析Class
  • 对override属性进行标记及验证。在Spring中配置存在lookup-method和repalce-method的,而这两个配置的加载其实就是将配置统一存放在BeanDefinition的methodOverrides属性里
  • 应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作
  • 创建bean

1.5.1 处理ovverride属性

查看AbstractBeanDefinition类的prepareMethodOverrides方法:

/**
* 处理override属性
* @throws BeanDefinitionValidationException 异常
*/
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   if (hasMethodOverrides()) {//判断是否存在overrides属性
      getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
   }
}
/**
* 验证和准备overrides属性。
* @param mo MethodOverride
* @throws BeanDefinitionValidationException 异常
*/
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) {
      //标记MethodOverrides暂未被覆盖, 避免参数类型检查的开销
      mo.setOverloaded(false);
   }
}

在Spring配置中存在lookup-method和repalce-method两个功能,而这两个配置的加载其实就是将配置统一存放在BeanDefinition中的methodOverrides属性里,这两个功能实现原理其实是在bean实例化的时候如果检测到存在methodOverrides属性里,会动态为当前的bean生成代理并使用对应的拦截器为bean做增强处理。相关实现在bean的实例化部分详细介绍。

1.5.2 实例化的前置处理

在真正调用doCreate()方法创建bean的实例前使用了这样一个方法resolveBeforeInstantiation(beanName, mbd) 对BeanDefinition中的属性做些前置处理。当然,无论其中是否又相应的逻辑实现我们都可以理解,因为真正逻辑实现前后留有处理函数也是可扩展的一种体现,但是,这并不重要,在函数中还提供了一种短路判断:

if (bean != null) {
   return bean;
}

当经过前置处理后返回的结果如果不为空,那么会直接略过后续的Bean的创建而直接返回结果。这一特性虽然很容易被忽略,但是却起着至关重要的作用,AOP功能就是基于这里的判断的。

/**
* 实例化的前置处理
* @param beanName beanName
* @param mbd      融合的RootBeanDefinition
* @return 快捷的Bean实例(可能为空)
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;

   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {//尚未被解析
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);//确定目标类型
         if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);//实例化前的后处理器应用
            if (bean != null) {
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);//实例化后的后处理器应用
            }
         }
      }

      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

applyBeanPostProcessorsBeforeInstantiation以及applyBeanPostProcessorsAfterInitialization实现非常简单,就是的前置处理和后置处理。

1.5.2.1 实例化前的后处理器应用

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

/**
* 实例化前的后处理器应用。
* 也就是将AbstractBeanDefinition转换为BeanWrapper前的处理。给子类一个修改BeanDefinition的机会。可能是AOP或者其他方式
* @param beanClass 要实例化的bean的类
* @param beanName  beanName
* @return 指定的bean对象
*/
@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;
}

1.5.2.2 实例化后的后处理器应用

Spring中的规则是在bean的初始化后尽可能保证将注册的后处理器的postProcessAfterInitialization方法应用到该bean中,因为如果返回的bean不为空,那么便不会再次经历普通bean的创建过程,所以只能在这里应用后处理器的postProcessAfterInitialization方法:

/**
* 实例化后的后处理器应用
* @param existingBean 已经存在的bean
* @param beanName     beanName
* @return 可能被修改过的bean对象
* @throws BeansException 异常
*/
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
   Object result = existingBean;

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

1.6 循环依赖

1.6.1 什么是循环依赖

循环依赖就是循环引用,就是两个或多个bean相互之间持有对方的引用,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则他们最终会形成一个环。如下所示:

Image.png

循环调用是无法解决的,除非有终结条件,否则就是死循环,最终导致内存溢出错误。

1.6.2 Spring如何解决循环依赖

检测循环依赖相对比较容易,Bean在创建的时候可以给该Bean打标,如果递归调用回来发现正在创建中的话,即说明了循环依赖了。Spring出现循环依赖的场景有:

  • 构造器的循环依赖
  • field属性set的循环依赖

如下,三个测试类:

public class CircleA {
    private CircleB circleB;

    public CircleA() {
    }

    public CircleA(CircleB circleB) {
        this.circleB = circleB;
    }

    public void setCircleB(CircleB circleB) {
        this.circleB = circleB;
    }
}
public class CircleB {
    private CircleC circleC;

    public CircleB() {
    }

    public CircleB(CircleC circleC) {
        this.circleC = circleC;
    }

    public void setCircleC(CircleC circleC) {
        this.circleC = circleC;
    }
}
public class CircleC {
    private CircleA circleA;

    public CircleC() {
    }

    public CircleC(CircleA circleA) {
        this.circleA = circleA;
    }

    public void setCircleA(CircleA circleA) {
        this.circleA = circleA;
    }
}

1.6.2.1 构造器循环依赖(这个Spring解决不了)

通过前面的一些代码阅读,我们知道Spring容器会将每个正在创建的Bean标识放在一个“当前创建Bean池”(singletonsCurrentlyInCreation)中,Bean在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在这个池中了,则抛出异常BeanCurrentlyInCreationException异常表示循环依赖。对于创建完毕的Bean将从“当前创建Bean池”中清除掉

Spring容器先创建单例CircleA,CircleA依赖CircleB,然后将A放在“当前创建Bean池”中,此时创建CircleB,CircleB依赖CircleC,然后将CircleB放在“当前创建Bean池”中;此时创建CircleC,CircleC又依赖CircleA,但是此时CircleA已经在池中了,所以会报错:

配置如下:

<?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-4.0.xsd">

    <bean id="a" class="com.bianjf.bean.CircleA">
        <constructor-arg index="0" ref="b"/>
    </bean>

    <bean id="b" class="com.bianjf.bean.CircleB">
        <constructor-arg index="0" ref="c"/>
    </bean>

    <bean id="c" class="com.bianjf.bean.CircleC">
        <constructor-arg index="0" ref="a"/>
    </bean>
</beans>

测试代码如下:

@Test

public void constructorTest() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanCircleConstructorTest.xml");
    CircleA a = (CircleA) context.getBean("a");
    System.out.println(a);
    context.close();
}

最终运行会报错:

Image.png

1.6.2.2 setter循环依赖

通过setter注入方式构成的循环依赖,对于setter注入方式造成的依赖是通过Spring容器提前暴露刚完成的构造器注入但未完成其他步骤(如setter注入)的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使其他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-4.0.xsd">
    <bean id="a" class="com.bianjf.bean.CircleA">
        <property name="circleB" ref="b"/>
    </bean>

    <bean id="b" class="com.bianjf.bean.CircleB">
        <property name="circleC" ref="c"/>
    </bean>

    <bean id="c" class="com.bianjf.bean.CircleC">
        <property name="circleA" ref="a"/>
    </bean>
</beans>

测试类如下:

@Test

public void setTest() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanCircleTest.xml");
    CircleA a = (CircleA) context.getBean("a");
    System.out.println(a);
    context.close();
}

具体步骤如下:

  • Spring容器创建单例“circleA”bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的bean,并将“circleA”标识符放到“当前创建bean池”,然后进行setter注入“circleB”
  • Spring容器创建单例“circleB”bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的bean,并将“circleB”标识符放到“当前创建bean池”,然后进行setter注入“circleC”
  • Spring容器创建单例“circleC”bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的bean,并将“circleC”标识符放到“当前创建bean池”,然后进行setter注入“circleA”。进行注入“circleA”时由于提前暴露了ObjectFactory工厂,从而使用它返回提前暴露一个创建中的bean
  • 最后在依赖注入“circleB”和“circleA”,完成setter注入

对于scope是prototype的依赖是无法解决循环依赖的。

1.7 创建bean

当经历过resolveBeforeInstantiation方法后,程序有两个选择:

  • 如果创建了代理或者说重写了InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法并在方法postProcessBeforeInstantiation中改变了bean,则直接返回
  • 否则需要进行常规的bean创建。

而常规bean的创建就是在doCreationBean中完成的:

/**
* 真实的创建指定的Bean。在调用这个方法之前的前置处理已经发生了。
* @param beanName beanName
* @param mbd      融合的属性RootBeanDefinition
* @param args     构造器参数。可能为空
* @return 创建的Bean对象
* @throws BeanCreationException Bean创建异常
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
   //Bean的包装器获取 Start
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {//单例模式
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);//删除缓存
   }
   if (instanceWrapper == null) {//缓存中不存在, 则直接创建Bean包装器
      //根据指定的bean使用对应的策略创建新的实例, 如: 工厂方法、构造函数自动注入、简单初始化
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   //Bean的包装器获取 End

   Object bean = instanceWrapper.getWrappedInstance();

   Class<?> beanType = instanceWrapper.getWrappedClass();

   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            //应用MergedBeanDefinitionPostProcessors
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         } catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   /*
    * 是否需要提早曝光: 单例&允许循环依赖&当前bean正在创建中, 检测循环依赖
    */
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));

   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }

      //为避免后期循环依赖, 可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   //初始化bean实例
   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);
      if (earlySingletonReference != null) {//earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
         if (exposedObject == bean) {//如果exposedObject没有在初始化方法中被改变, 也就是没有被增强
            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 " +
                           "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

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

   return exposedObject;
}

日志与异常非常重要,但是我们这里不深入探讨日志及异常,我们先看看函数的概要思路:

  • 如果是单例,则先清除缓存
  • 实例化bean,将BeanDefinition转换为BeanWrapper。转换是一个复杂的而过程,但是我们可以尝试概括大致功能:
    • 如果存在工厂方法则使用工厂方法进行初始化
    • 一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化
    • 如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行bean的初始化
  • MergedBeanDefinitionPostProcessor的应用:bean合并后的处理,Autowired注解正是通过此方法实现诸如类型的预解析
  • 依赖处理:在Spring中会有循环依赖的情况。例如当A中含有B的属性,而B中又含有A的属性时就会构成一个循环依赖。此时如果A和B都是单例,那么在Spring中的处理方式就是当创建B的时候,设计自动注入A的步骤时,并不是直接再次创建A,而是通过放入缓存中的ObjectFactory来创建实例,这样就解决了循环依赖问题
  • 注册属性填充,将所有属性填充至bean的实例中
  • 循环依赖检查
  • 注册DisposableBean:如果配置了destory-method,这里需要注册以便于在销毁时调用
  • 完成创建并返回

1.7.1 创建bean的实例

当我们了解循环依赖以后就可以深入分析创建bean的每个步骤了,首先从createBeanInstance开始:

/**
* 创建一个新的实例。使用的策略是: 工厂方法, 构造注入或者简单实例
* @param beanName beanName
* @param mbd 融合所有属性的RootBeanDefinition
* @param args 构造参数
* @return BeanWrapper
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   Class<?> beanClass = resolveBeanClass(mbd, beanName);//解析class

   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());
   }

   //通过实例供应获取 Start
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
   }
   //通过实例供应获取 End

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

   boolean resolved = false;//是否已经解析过
   boolean autowireNecessary = false;//构造函数是否自动注入
   if (args == null) {
      //一个类有多个构造函数, 每个构造函数都有不同的参数, 所以调用前需要先根据参数锁定构造函数或对应的工厂方法 Start
      synchronized (mbd.constructorArgumentLock) {
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
      //一个类有多个构造函数, 每个构造函数都有不同的参数, 所以调用前需要先根据参数锁定构造函数或对应的工厂方法 End
   }

   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() == AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      return autowireConstructor(beanName, mbd, ctors, args);//构造函数自动注入
   }

   //默认构造的首选构造函数 Start
   ctors = mbd.getPreferredConstructors();
   if (ctors != null) {
      return autowireConstructor(beanName, mbd, ctors, null);
   }
   //默认构造的首选构造函数 End

   //使用默认构造函数构造
   return instantiateBean(beanName, mbd);
}

主要的过程如下:

  1. 如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method,那么Spring会尝试使用instantiateUsingFactoryMethod(beanName, mbd, args) 方法根据RootBeanDefinition中的配置生成bean的实例
  2. 解析构造函数并进行构造函数的实例化。因为一个bean对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring会根据参数及类型去判断最终会使用哪个构造函数进行实例化。但是,判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod中。

1.7.1.1 autowireConstructor

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

/**
* 使用带有参数的构造函数初始化Bean, 将其封装在BeanWrapper中
* @param beanName beanName
* @param mbd RootBeanDefinition
* @param ctors 构造器
* @param explicitArgs 构造函数参数
* @return BeanWrapper
*/
protected BeanWrapper autowireConstructor(
      String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
   return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
/**

* 自动装配构造函数。
* 如果指定了显示的构造函数参数值, 也将使用此方法
* @param beanName     beanName
* @param mbd          融合的RootBeanDefinition
* @param chosenCtors  选定的候选构造函数
* @param explicitArgs 通过getBean方法以编程方式传入的值
* @return Bean装配器
*/
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
   BeanWrapperImpl bw = new BeanWrapperImpl();
   this.beanFactory.initBeanWrapper(bw);

   Constructor<?> constructorToUse = null;
   ArgumentsHolder argsHolderToUse = null;
   Object[] argsToUse = null;//构造函数参数

   //解析构造参数 Start
   if (explicitArgs != null) {//如果getBean方法指定了构造函数那么直接使用
      argsToUse = explicitArgs;
   } else {//getBean没有指定构造函数, 那么则尝试从配置文件中解析
      Object[] argsToResolve = null;//配置的构造函数参数
      //尝试从缓存中获取 Start
      synchronized (mbd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse != null && mbd.constructorArgumentsResolved) {
            argsToUse = mbd.resolvedConstructorArguments;//从缓存中获取
            if (argsToUse == null) {
               argsToResolve = mbd.preparedConstructorArguments;//配置的构造函数参数
            }
         }
      }
      //尝试从缓存中获取 End

      if (argsToResolve != null) {//缓存中存在
         /*
          * 解析参数类型, 如给定方法的构造函数A(int, int)则通过此方法后就会把配置中的
          * ("1", "1")转换为(1, 1), 缓存中的值可能是原始值也可能是最终值
          */
         argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
      }
   }
   //解析构造参数 End

   //没有定位到缓存 Start
   if (constructorToUse == null || argsToUse == null) {
      //获取构造函数 Start
      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);
         }
      }
      //获取构造函数 End

      //如果只有一个构造函数(无参构造)并且没有指定构造函数的参数 Start
      if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
         Constructor<?> uniqueCandidate = candidates[0];//构造函数
         if (uniqueCandidate.getParameterCount() == 0) {//无参构造函数
            synchronized (mbd.constructorArgumentLock) {
               mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;//无参构造
               mbd.constructorArgumentsResolved = true;
               mbd.resolvedConstructorArguments = EMPTY_ARGS;
            }
            bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
            return bw;
         }
      }
      //如果只有一个构造函数(无参构造)并且没有指定构造函数的参数 End

      boolean autowiring = (chosenCtors != null ||
            mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
      ConstructorArgumentValues resolvedValues = null;

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

      AutowireUtils.sortConstructors(candidates);//先对构造函数进行排序(public函数优先参数数量降序、非public构造函数参数数量降序)
      int minTypeDiffWeight = Integer.MAX_VALUE;
      Set<Constructor<?>> ambiguousConstructors = null;
      LinkedList<UnsatisfiedDependencyException> causes = null;


      for (Constructor<?> candidate : candidates) {
         int parameterCount = candidate.getParameterCount();//构造函数参数的数量

         if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
            /*
             * 如果已经找到选用的构造函数或者需要的参数个数小于当前的构造函数参数个数则终止,
             * 因为已经按照参数个数降序排序
             */
            break;
         }

         //参数个数不相等 Start
         if (parameterCount < minNrOfArgs) {//参数个数不相等
            continue;
         }
         //参数个数不相等 End

         ArgumentsHolder argsHolder;

         Class<?>[] paramTypes = candidate.getParameterTypes();

         if (resolvedValues != null) {//有参构造
            try {
               //从注解(ConstructorProperties)上获取参数名称
               String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
               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, candidates.length == 1);
            } catch (UnsatisfiedDependencyException ex) {
               if (logger.isTraceEnabled()) {
                  logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
               }

               if (causes == null) {
                  causes = new LinkedList<>();
               }
               causes.add(ex);
               continue;
            }
         } else {//无参构造
            if (parameterCount != 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 != null) {
         argsHolderToUse.storeCache(mbd, constructorToUse);//将解析的构造函数加入缓存
      }
   }
   //没有定位到缓存 End

   Assert.state(argsToUse != null, "Unresolved constructor arguments");
   bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));//将构造的实例加入BeanWrapper中
   return bw;
}

这个函数的功能主要有以下:

(1) 构造函数参数的确定

  • 根据explicitArgs参数判定

如果传入的参数explicitArgs不为空,那么可以直接确定参数,因为explicitArgs参数是在调用Bean的时候用户指定的,在BeanFactory类中存在这样的方法:

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

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

  • 缓存中获取

确定参数的办法如果之前已经分析过,也就是说构造函数参数已经记录在缓存中,那么便可以直接拿来使用。在缓存中缓存的可能是参数的最终类型也可能是参数的初始类型。例如,构造函数参数要求的是int类型,但是原始的参数可能是String类型的“1”,那么即使再缓存中得到了参数,也需要经过类型转换器的过滤以确保参数类型与对应的构造函数参数类型完全对应。

  • 配置文件获取

如果不能根据传入的参数explicitArgs确定构造函数的参数也无法在缓存中得到相关的信息,那么只能开启其他的分析了。

首先从配置文件开始,Spring中可以通过调用BeanDefinition的getConstructorArgumentValues()来获取配置的构造函数信息,有了配置中的信息便可以获取对应的参数值信息了,获取参数值的信息包括直接指定值,如:直接指定构造函数中某个值为原始类型String类型,或者是一个对其他bean的引用。

(2) 构造函数的确定

经过了第一步后已经确定了构造函数的参数,然后根据构造参数锁定对应的构造函数,而匹配的方法就是根据参数个数匹配。所以在匹配之前需要先对构造函数按照public构造函数优先参数数量降序、非public构造函数参数数量降序。这样可以在遍历的情况下迅速判断排在后面的构造函数参数个数是否符合条件。

(3) 根据确定的构造函数转换对应的参数类型

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

(4) 构造函数不确定性的校验

有时候即使构造函数、参数名称、参数类型、参数值都确定后也不一定会直接锁定构造函数,不同构造函数的参数为父子关系,所以Spring在最后又做了一次验证

(5) 根据实例化策略以及得到的构造函数及构造函数参数实例化bean

1.7.1.2 instantiateBean

经历了带有参数的构造函数的实例构造,下面是不带参数的构造函数实例化过程:

/**
* 使用默认的构造函数初始化Bean
* @param beanName beanName
* @param mbd 融合的RootBeanDefinition
* @return Bean装配器
*/
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
   try {
      Object beanInstance;
      if (System.getSecurityManager() != null) {//权限校验
         beanInstance = AccessController.doPrivileged(
               (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext());
      } else {
         //通过指定的策略初始化(CGLIB)
         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
      }

      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
   } catch (Throwable ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
   }
}

这个方法并没有实质性的逻辑

1.7.1.3 实例化策略

实例化过程中提到过实例化策略。其实,经过前面的解析,我们已经得到了足以实例化的所有相关信息,完全可以使用最简单的反射方法直接反射来构造实例对象,但是Spring并没有这么做:

SimpleInstantiationStrategy#instantiate() 函数代码如下:

/**
* 初始化
* @param bd       融合属性的RootBeanDefinition
* @param beanName beanName
* @param owner    BeanFactory(通过在beanName添加&)
* @return Object
*/
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
   if (!bd.hasMethodOverrides()) {//不存在overrides属性
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;//构造函数
         if (constructorToUse == null) {
            final Class<?> clazz = bd.getBeanClass();//对应的class
            if (clazz.isInterface()) {//如果这个class是一个接口, 则抛出异常(无法实例化)
               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 {//存在override属性, 则使用CGLIB子类
      return instantiateWithMethodInjection(bd, beanName, owner);
   }
}

CglibSubclassingInstantiationStrategy#instantiate(ctor, args)代码如下:

public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
   Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
   Object instance;
   if (ctor == null) {
      instance = BeanUtils.instantiateClass(subclass);
   } else {
      try {
         Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
         instance = enhancedSubclassConstructor.newInstance(args);
      } catch (Exception ex) {
         throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
               "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
      }
   }

   Factory factory = (Factory) instance;
   factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
         new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
         new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
   return instance;
}

我们可以看到,如果beanDefinition.getMethodOverrides()为空,也就是用户没有使用replace或者lookup的配置方法,那么直接使用反射的方式,简单快捷。但是如果有这两个特性,就需要使用动态代理的方式将包含两个特性对应的逻辑的拦截增强器设置进去,这样才可以保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例

1.7.2 记录创建bean的ObjectFactory

doCreate函数中也有这样一段代码:

/*
* 是否需要提早曝光: 单例&允许循环依赖&当前bean正在创建中, 检测循环依赖
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
      isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
   if (logger.isTraceEnabled()) {
      logger.trace("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
   }

   //为避免后期循环依赖, 可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

这段代码并不复杂,这时我们需要从全局的角度思考Spring的依赖解决办法:

  • earlySingletonExposure:提早曝光的单例
  • mbd.isSingleton():是否是单例
  • this.allowCircularReferences:是否允许循环依赖。在配置中没有找到如何配置,但是在AbstractRefreshableApplicationContext提供了设置函数,可以通过硬编码的方式进行设置或者可以通过自定义命名空间进行设置
  • isSingletonCurrentlyInCreation(beanName):该bean是否在创建中。在Spring中,会有专门的属性默认为DefaultSingletonBeanRegistry的singletonsCurrentlyInCreation来记录bean的加载状态。在bean开始创建前会将beanName记录在属性中,在bean创建结束后会将beanName从属性中移除。这个其实是在DefaultSingletonBeanRegistry类的public Object getSingleton(String beanName, ObjectFactory singletonFactory)函数的beforeSingletonCreation(beanName)和afterSingletonCreation(beanName)中进行记录和删除的。

经过上述分析了解变量earlySingletonExposure是否是单例、是否允许循环依赖、是否对应的bean正在创建的条件的综合。

我们以最简单的AB循环依赖为例,类A中包含属性类B,而类B中又包含属性类A,那么初始化beanA的过程如下:

Image.png

从图中我们可以看到,在创建A的时候首先会记录A所对应的beanName,并将beanA的创建工厂加入缓存中,而在对A的属性填充也就是调用populate方法的时候又会再一次对B进行递归创建。同样,因为在B中也存在A属性,因此在实例化B的populate方法中又会再次初始化B,也就是最后调用getBean(A)。在getBean(A)时并不是直接去实例化A,而是先去检测缓存中是否有已经创建好的对应的bean,或者是否已经创建好的ObjectFactory,而此时对于A的ObjectFactory我们早已创建,所以便不会再去向后执行,而是直接调用ObjectFactory去创建A,最关键的就是ObjectFactory的实现:

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
/**
* 获取早期的bean引用, 主要是为了解决循环引用的问题。
* 这里还有一步处理: 就是AOP的织入
* @param beanName beanName
* @param mbd RootBeanDefinition
* @param bean 实例
* @return bean实例
*/
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;

   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
   return exposedObject;
}

在getEarlyBeanReference函数中没有太多的逻辑处理,或者说除了后处理器的调用外没有别的处理工作。

根据以上分析,基本可以理清Spring处理循环依赖的解决办法,在B中创建依赖A时通过ObjectFactory提供的实例化方法来中断A中的属性填充,使B中持有的A仅仅是刚刚初始化并没有填充任何属性的A,而这正初始化A的步骤还是在最开始创建A的时候进行的,但是因为A与B中的A所表示的属性地址是一样的,所以在A中创建好的属性填充自然可以通过B中的A获取,这样就解决了循环依赖的问题

1.7.3 属性注入

我们之前提到了populateBean这个函数,主要是对属性进行填充的,代码如下:

/**
* 填充bean实例的属性
* @param beanName beanName
* @param mbd 原始的配置
* @param bw Bean装配器
*/
@SuppressWarnings("deprecation")
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

   //数据校验 Start
   if (bw == null) {
      if (mbd.hasPropertyValues()) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      } else {//没有可填充的属性
         return;
      }
   }
   //数据校验 End

   /*
    * 给InstantiationAwareBeanPostProcessor最后一次机会在属性设置前来改变bean
    * 如: 可以用来支持属性注入的类型
    */
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {//此函数可以控制程序是否继续进行属性填充
               return;
            }
         }
      }
   }

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

   int resolvedAutowireMode = mbd.getResolvedAutowireMode();//输入类型
   if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      //根据名称自动注入 Start
      if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }
      //根据名称自动注入 End

      //根据类型自动注入 Start
      if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }
      //根据类型自动注入 End
      pvs = newPvs;
   }

   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();//后处理器已经初始化
   boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.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) {
      if (filteredPds == null) {
         filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      }
      checkDependencies(beanName, mbd, filteredPds, pvs);
   }

   if (pvs != null) {
      applyPropertyValues(beanName, mbd, bw, pvs);//将属性应用到bean中
   }
}

populateBean函数的处理流程如下:

  • InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation函数的应用,此函数可以控制程序是否继续进行属性填充
  • 根据注入类型(byName/byType),提取依赖的bean,并同意存入PropertyValues中
  • 应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性再次处理,典型的应用时RequiredAnnotationBeanPostProcessor类中对属性的验证
  • 将所有PropertyValues中的属性填充至BeanWrapper中

1.7.3.1 autowireByName

根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中,如下,是byName功能的代码:

/**
* 根据名称自动注入
* @param beanName beanName
* @param mbd RootBeanDefinition
* @param bw bean装配器
* @param pvs 可变的属性值
*/
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);//寻找bw中需要依赖注入的属性
   for (String propertyName : propertyNames) {
      if (containsBean(propertyName)) {
         //递归初始化相关的bean Start
         Object bean = getBean(propertyName);
         pvs.add(propertyName, bean);
         //递归初始化相关的bean End

         registerDependentBean(propertyName, beanName);//注册依赖

         if (logger.isTraceEnabled()) {
            logger.trace("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");
         }
      }
   }
}

这个函数很简单,无非是在传入的参数pvs中找出已经加载的bean,并递归实例化,进而加入到pvs中

1.7.3.2 autowireByType

autowireByType与autowireByName在使用程度上很相似,但是其实现功能的复杂度却完全不同:

/**
* 根据类型自动注入
* @param beanName beanName
* @param mbd RootBeanDefinition
* @param bw bean装配器
* @param pvs 可变的属性值
*/
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

   //自定义的类型转换器 Start
   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }
   //自定义的类型转换器 End

   Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);//寻找bw中需要依赖注入的属性
   for (String propertyName : propertyNames) {
      try {
         PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);

         if (Object.class != pd.getPropertyType()) {
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);//探测指定属性的set方法

            boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);

            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.isTraceEnabled()) {
                  logger.trace("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中需要依赖注入的属性,同样对于根据类型自动匹配的实现来讲第一步也是寻找bw中需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的bean,其中最复杂的就是寻找匹配的bean。同时,Spring提供了对集合的类型注入的支持,如下方式:

@Autowired
private List<Test> tests;

Spring将会把所有与Test匹配的类型寻找出来并注入到tests属性中,正式由于这一因素,所以在autowireByType函数中,新建了局部遍历autowiredBeanNames,用于存储所有依赖的bean,如果只是对非集合类型的属性注入来说,此属性并无用处

对于寻找类型匹配的逻辑实现封装在了DefaultListableBeanFactory#resolveDependency 函数中:

/**
* 解析依赖
* @param descriptor 字段/方法/构造器的描述
* @param requestingBeanName beanName
* @param autowiredBeanNames autowiredBeanNames
* @param typeConverter 类型转换器
* @return 对象实例
* @throws BeansException Bean异常
*/
@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()) {//Java注入
      return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
   } else {//通用的处理
      Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);

      if (result == null) {
         result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
      }
      return result;
   }
}
/**
* 解析依赖
* @param descriptor 字段/方法/构造器的描述
* @param beanName beanName
* @param autowiredBeanNames autowiredBeanNames
* @param typeConverter 类型转换器
* @return 解析的结果依赖对象
* @throws BeansException BeanException
*/
@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;
      }

      //支持@Value注解 Start
      Class<?> type = descriptor.getDependencyType();
      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());
         try {
            return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
         } catch (UnsupportedOperationException ex) {
            return (descriptor.getField() != null ?
                  converter.convertIfNecessary(value, type, descriptor.getField()) :
                  converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
         }
      }
      //支持@Value注解 End

      Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);//解析各种类型
      if (multipleBeans != null) {
         return multipleBeans;
      }

      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (matchingBeans.isEmpty()) {
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         return null;
      }

      String autowiredBeanName;

      Object instanceCandidate;

      if (matchingBeans.size() > 1) {
         autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
         if (autowiredBeanName == null) {
            if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
               return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
            } else {
               return null;
            }
         }

         instanceCandidate = matchingBeans.get(autowiredBeanName);
      } else {
         Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
         autowiredBeanName = entry.getKey();
         instanceCandidate = entry.getValue();
      }

      if (autowiredBeanNames != null) {
         autowiredBeanNames.add(autowiredBeanName);
      }

      if (instanceCandidate instanceof Class) {
         instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }

      Object result = instanceCandidate;

      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);
   }
}
/**
* 各种集合类型解析
* @param descriptor 字段/方法/构造器的描述
* @param beanName beanName
* @param autowiredBeanNames autowiredBeanNames
* @param typeConverter 类型转换器
* @return Object
*/
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

   Class<?> type = descriptor.getDependencyType();

   if (descriptor instanceof StreamDependencyDescriptor) {//Stream类型
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (autowiredBeanNames != null) {
         autowiredBeanNames.addAll(matchingBeans.keySet());
      }

      Stream<Object> stream = matchingBeans.keySet().stream()
            .map(name -> descriptor.resolveCandidate(name, type, this))
            .filter(bean -> !(bean instanceof NullBean));
      if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
         stream = stream.sorted(adaptOrderComparator(matchingBeans));
      }

      return stream;
   } else if (type.isArray()) {//数组类型
      Class<?> componentType = type.getComponentType();
      ResolvableType resolvableType = descriptor.getResolvableType();
      Class<?> resolvedArrayType = resolvableType.resolve(type);
      if (resolvedArrayType != type) {
         componentType = resolvableType.getComponentType().resolve();
      }

      if (componentType == null) {
         return null;
      }
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, 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(), resolvedArrayType);
      if (result instanceof Object[]) {
         Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
         if (comparator != null) {
            Arrays.sort((Object[]) result, comparator);
         }
      }

      return result;
   } 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 (result instanceof List) {
         if (((List<?>) result).size() > 1) {
            Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
            if (comparator != null) {
               ((List<?>) result).sort(comparator);
            }
         }
      }
      return result;
   } else if (Map.class == type) {//Map
      ResolvableType mapType = descriptor.getResolvableType().asMap();
      Class<?> keyType = mapType.resolveGeneric(0);
      if (String.class != keyType) {
         return null;
      }

      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;
   }
}

寻找类型匹配执行顺序时,首先尝试使用解析器进行解析,如果解析器没有成功解析,那么可能是使用默认的解析器没有做任何处理,或者是使用了自定义的解析器。但是对于集合等类型来说并不在解析范围之内,所以再次对不同类型进行不同情况的处理,但是大致思路是相似的。

1.7.3.3 applyPropertyValues

程序运行到这里,已经完成了对所有注入属性的获取,但是获取的属性是以PropertyValues形式存在的,还并没有应用到已经实例化的bean中,这个工作在applyPropertyValues中:

/**
* 应用给定的属性值
* @param beanName beanName
* @param mbd RootBeanDefinition
* @param bw bean装配器
* @param pvs 属性值
*/
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;

   //获取属性值 Start
   if (pvs instanceof MutablePropertyValues) {
      mpvs = (MutablePropertyValues) pvs;
      if (mpvs.isConverted()) {
         try {
            bw.setPropertyValues(mpvs);
            return;
         } catch (BeansException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
         }
      }
      original = mpvs.getPropertyValueList();
   } else {
      original = Arrays.asList(pvs.getPropertyValues());
   }
   //获取属性值 End

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

   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();
         if (originalValue == AutowiredPropertyMarker.INSTANCE) {
            Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
            if (writeMethod == null) {
               throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
            }
            originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
         }
         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);
         }

         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();
   }

   try {
      bw.setPropertyValues(new MutablePropertyValues(deepCopy));
   } catch (BeansException ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
   }
}

1.7.4 初始化bean

在bean配置时bean中有一个init-method属性,这个属性的作用是在bean实例化前调用init-method指定的方法来根据用户业务进行相应的实例化。这个方法的执行位置是在Spring中已经执行过bean的实例化,并且进行了属性的填充,而就在这时将会调用用户设定的初始化方法:

/**
* 初始化给定的bean实例。主要是应用工厂的初始化方法和BeanPostProcessor的方法。
* 这里可能还会调用InitializingBean中的afterPropertiesSet方法
* @param beanName beanName
* @param bean 实例对象
* @param mbd mbd
* @return 具体的实例
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   //执行Aware相关方法 Start
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);//执行aware相关的方法(主要是适配具体的Aware, 然后set相关属性)
         return null;
      }, getAccessControlContext());
   } else {
      invokeAwareMethods(beanName, bean);//执行aware相关的方法(主要是适配具体的Aware, 然后set相关属性)
   }
   //执行Aware相关方法 End

   //执行BeanPostProcessor的postProcessBeforeInitialization方法 Start
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
   //执行BeanPostProcessor的postProcessBeforeInitialization方法 End

   //执行初始化方法(InitializingBean.afterPropertiesSet或用户自定义的) Start
   try {
      invokeInitMethods(beanName, wrappedBean, mbd);//执行初始化方法
   } catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   //执行初始化方法(InitializingBean.afterPropertiesSet或用户自定义的) End

   //执行BeanPostProcessor的postProcessAfterInitialization方法 End
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
   //执行BeanPostProcessor的postProcessAfterInitialization方法 End

   return wrappedBean;
}

这里执行了BeanPostProcessor的两个方法,不做过多解释。将主要的初始化工作委托给了invokeInitMethods函数,具体代码如下:

/**
* 执行初始化方法
* @param beanName beanName
* @param bean bean
* @param mbd RootBeanDefinition
* @throws Throwable 异常
*/
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
   //如果这个bean是一个InitializingBean的话, 则执行其afterPropertiesSet方法 Start
   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
      if (logger.isTraceEnabled()) {
         logger.trace("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();
      }
   }
   //如果这个bean是一个InitializingBean的话, 则执行其afterPropertiesSet方法 End

   //用户自定义的初始化方法 Start
   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);
      }
   }
   //用户自定义的初始化方法 End
}

这个函数主要做了两个事情:

  • 调用InitializingBean的afterPropertiesSet方法。这个其实很重要,SpringMVC的HandlerMapping扫描就是从这里开始的,具体到SpringMVC再做详细介绍
  • 执行自定义的初始化方法。这个方法就是手动指定的init方法

1.7.5 注册DisposableBean

Spring中不但提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口,对于销毁方法的扩展,除了我们熟悉的destory-method方法外,用户还可以注册后处理器DestructionAwareBeanPostProcessor来统一处理bean的销毁方法,代码如下:

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
   AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
   if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
      if (mbd.isSingleton()) {
         registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
      } else {
         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));
      }
   }
}