阅读 36

Spring源码解析——Bean加载(doCreateBean方法补充)


1. doCreateBean方法解析

还是一样的步骤,先来整体分析一下doGreateBean方法,后面再详细分步骤解析:

/**
 * 核心方法(真正创建Bean的方法):创建Bean实例对象,并且生命周期的动作大部分都在这里
 */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

   // BeanWrapper:包装对象,内部最核心的字段就是咱们的真实实例。它提供了一些额外的接口方法,比如属性访问器
   BeanWrapper instanceWrapper = null;
   // 如果是单例,则先清除缓存
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   // 如果缓存中没有找到对应的结果:
   if (instanceWrapper == null) {
        // 则创建Bean实例,并将其包装到BeanWrapper实例中
        // createBeanInstance方法创建出来真实的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 {
            // 后处理器调用点:合并bd信息,因为接下来就是populate处理依赖了.. 
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            ... // 抛异常
         }
         mbd.postProcessed = true;
      }
   }

   // 是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
         ... // 日志打印
      }
      // 为避免后期循环依赖,可以在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())) {
         ... // 抛异常
      }
      else {
         ... // 抛异常
      }
   }

   if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      // earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
      // 条件成立:说明当前bean实例 从 2级缓存获取到了...
      // 说明产生循环依赖了...3级缓存 当前对象的ObjectFactory.getObject() 被调用过
      if (earlySingletonReference != null) {
         // 如果exposedObject没有在初始化方法中被改变,也就是没有被增强
         // 条件成立有几种情况?
		// 1.当前“真实实例”不需要被代理
		// 2.当前“实例”已经被代理过了...是在ObjectFactory.getObject() 方法调用时 实现的增强代理。
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            // 获取依赖当前bean的 其它beanName
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               // 检测依赖
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            // 为什么有问题?
            // 因为bean创建后其所依赖的bean一定是已经创建的
            // actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有没全部创建完,也就是说存在循环依赖
            if (!actualDependentBeans.isEmpty()) {
               ... // 抛异常
            }
         }
      }
   }

   try {
      // 判断当前bean实例是否需要注册 析构回调。当容器销毁时,会给当前bean的析构方法进行回调。
      // 根据scope注册bean
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      ... // 抛异常
   }

   return exposedObject;
}
复制代码

上面代码中,我们整体串了一遍doCreateBean方法的整体流程,为了减少代码量和文章篇幅,代码中省略了错误日志打印和异常抛出。

我们来总结一下上面代码的执行过程:

  • 获取BeanWrapper:如果是单例模式,首先从缓存中尝试 remove 移除对应的 Bean 对象,移除后该方法返回 BeanWrapper对象。

    // Instantiate the bean.实例化bean。
    // BeanWrapper:包装对象,内部最核心的字段就是咱们的真实实例。它提供了一些额外的接口方法,比如 属性访问器
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
    	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    复制代码
  • 获取BeanWrapper:如果缓存中没有找到目标结果,则通过createBeanInstance方法创建 Bean 实例(根据 BeanDefinition 最终结果转换为 BeanWrapper对象)

    // 如果缓存中没有找到对应的结果:
    if (instanceWrapper == null) {
    	// 则创建Bean实例,并将其包装到BeanWrapper实例中
    	// createBeanInstance方法创建出来真实的bean实例:
    	instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    复制代码
  • Bean 的依赖进行处理、填充、属性注入,并进行循环依赖检查,检测已经加载的 bean 是否已经出现了依赖循环,并判断是否要抛出异常:

    // 是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    		isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
    	if (logger.isTraceEnabled()) {
    		logger.trace("Eagerly caching bean '" + beanName +
    				"' to allow for resolving potential circular references");
    	}
    	// 为避免后期循环依赖,可以在bean初始化完成之前将创建实例的ObjectFactory加入工厂
    	// 对bean再一次依赖引用,主要应用SmartInstantiationAware BeanPostProcessor
    	// 其中我们熟知的AOP就是这样将advice动态织入bean中,若没有则直接返回bean,不做任何处理
    	addSingletonFactory(beanName, () -> 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())) {
    		... // 抛异常
    	}
    	else {
    		... // 抛异常
    	}
    }
    
    if (earlySingletonExposure) {
    	Object earlySingletonReference = getSingleton(beanName, false);
    	// earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
    	if (earlySingletonReference != null) {
    		// 条件成立有几种情况?
    		// 1.当前“真实实例”不需要被代理
    		// 2.当前“实例”已经被代理过了...是在ObjectFactory.getObject() 方法调用时 实现的增强代理。
    		if (exposedObject == bean) {
    			exposedObject = earlySingletonReference;
    		}
    		else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    			// 获取依赖当前bean的 其它beanName
    			String[] dependentBeans = getDependentBeans(beanName);
    			Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
    			for (String dependentBean : dependentBeans) {
    				// 检测依赖
    				if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    					actualDependentBeans.add(dependentBean);
    				}
    			}
    			// 为什么有问题?
    			// 因为咱们当前对象的AOP操作是在 当前方法的 initializeBean 这个方法完成的。
    			// 在这之前 外部其它bean持有到的当前的 “bean实例” 都是尚未增强的。
    			if (!actualDependentBeans.isEmpty()) {
    				... // 抛异常
    			}
    		}
    	}
    }
    复制代码
  • 注册 DisposableBean。如果XML配置了 destory-method,这里需要注册以便于销毁 bean 的时候调用;

    // 判断当前bean实例是否需要注册 析构回调。当容器销毁时,会给当前bean的析构方法进行回调。
    // 根据scope注册bean
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
    复制代码
  • 完成创建并返回

    return exposedObject;
    复制代码

接下来一步一步的详细分析一下:

2. 获取BeanWrapper

在分析createBeanInstance方法之前,先来了解一下 BeanWrapper 类以及它的作用:

  • 在Spring框架中,数据的提供是由 BeanDefinition 这个类来负责,而依赖的注入就需要通过 BeanWrapper
  • 可以把BeanWrapper 理解为是一个代理器,Spring框架会委托 BeanWrapper 去完成 Bean 属性的填充工作。
  • BeanWrapper 是一个接口,因此Bean 属性的填充工作实际上是交给其实现类 BeanWrapperImpl 去完成!

doCreateBean方法中,调用createBeanInstance创建BeanWrapper实例之前,会先尝试从缓存中获取 BeanWrapper 对象( 从factoryBeanInstanceCache 中进行 remove,并获取该方法的返回值,返回的结果就是BeanWrapper实例)。

如果缓存中没有,我们需要调用 createBeanInstance() 方法根据指定 Bean 使用对应的策略创建新的 BeanWrapper 实例。

// Instantiate the bean.实例化bean。
// BeanWrapper:包装对象,内部最核心的字段就是咱们的真实实例。它提供了一些额外的接口方法,比如 属性访问器
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}

// 如果缓存中没有找到对应的结果:
if (instanceWrapper == null) {
	// 则创建Bean实例,并将其包装到BeanWrapper实例中
	// createBeanInstance方法创建出来真实的bean实例:
	instanceWrapper = createBeanInstance(beanName, mbd, args);
}
复制代码

下面就来分析,创建BeanWrapper实例的方法:createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

/**
 * 创建beanWrapper的实例
 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
 * factory method, constructor autowiring, or simple instantiation.
 * @param beanName
 * @param mbd RootBeanDefinition
 * @param args
 * @return 返回一个BeanWrapper对象
 */
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   // 解析bean对象的class类型
   Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
   // 三个条件: 
   // beanClass != null --> bean对象的class类型不为null
   // !Modifier.isPublic(beanClass.getModifiers() ---> 表示class是非public类型的
   // !mbd.isNonPublicAccessAllowed() ---> bd中nonPublicAccessAllowed字段值为false
   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
       // 上述三个条件均成立,就抛异常
       ... // 抛异常
   }

   // 通过指定的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);
   }

   // 表示bd对应的构造信息是否已经解析成可以反射调用的构造方法method信息了...
   boolean resolved = false;
   // 是否自动匹配构造方法..
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
         // 一个类有多个构造函数,每个构造函数都有不同的参数,所以调用前需要先根据参数锁定构造函数和对应的工厂方法
         // resolvedConstructorOrFactoryMethod缓存这构造函数或工厂方法
         // 如果条件成立:说明bd的构造信息已经转化成可以反射调用的method了...
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            // 当resolvedConstructorOrFactoryMethod 有值时,且构造方法有参数,那么可以认为这个字段值就是true。
		   // 只有什么情况下这个字段是false呢?
		   // 1.resolvedConstructorOrFactoryMethod == null
		   // 2.当resolvedConstructorOrFactoryMethod 表示的是默认的构造方法,无参构造方法。
            resolved = true;
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
   // 如果已经解析过则使用缓存中已经解析好的构造函数方法不需要再次锁定
   if (resolved) {
      if (autowireNecessary) {
         // 构造函数自动注入
         // 如果有参数,那么就需要根据参数 去匹配合适的构造方法了...
         // 拿出当前Class的所有构造器,然后根据参数信息去匹配出一个最优的选项,然后执行最优的构造器创建出实例。
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
         // 使用默认构造函数构造(无参构造方法处理)
         return instantiateBean(beanName, mbd);
      }
   }

   // 典型的应用:@Autowired 注解打在了构造器方法上(需要根据参数解析构造函数...)
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   // 条件一:成立,后处理指定了构造方法数组
   // 条件二:mbd autowiredMode 一般情况是no
   // 条件三:条件成立,说明bean信息中配置了 构造参数信息。
   // 条件四:getBean时,args有参数..
   if (ctors != null ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      // 构造函数自动注入
      return autowireConstructor(beanName, mbd, ctors, args);
   }
   // 未指定构造参数,未设定偏好...则使用默认的无参数的构造方法进行创建实例
   return instantiateBean(beanName, mbd);
}
复制代码

下面我们重点去分析一下autowireConstructor这个方法:

2.1 autowireConstructor

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

/**
 * 带有参数的构造方法实例化
 * @param beanName 
 * @param mbd RootBeanDefinition
 * @param chosenCtors 候选构造函数(如果没有,则为 null)
 * @param explicitArgs 
 * @return 返回一个BeanWrapper对象
 */
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()) {
                  ... // 日志打印
               }
               // 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;
         }
         ... // 抛异常
      }
      else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
         ... // 抛异常
      }

      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) {
      ... // 抛异常
   }
}
复制代码

代码量很多,我们整体过一遍整个方法逻辑,其实现的功能考虑了以下几个方面:

2.1.1 构造函数参数的确定

  • 根据 explicitArgs 参数判断

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

Object getBean(String name, Object... args) throws BeansException;
复制代码

在获取 bean 的时候,用户不但可以指定 bean 的名称还可以指定 bean 所对应的构造函数或者工厂方法的方法参数,主要用于静态工厂方法的调用,而这里是需要给定完全匹配的参数的。所以,只要传入了 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中
 * @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;
}
复制代码

2.1.2 构造函数的确定

经过上面构造函数参数的确定,我们可以依据参数来锁定构造函数。我们需要先获取所有的候选的构造函数,如果用户传入构造函数那么直接确定为候选集合,否则需要我们根据 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));
    });
}
复制代码

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

获取参数名称有两种方式,一种是注解的方式直接获取,另一种是使用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);
   }
}
复制代码

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

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

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

/*
 * 将确定的构造函数转换为对应的参数类型
 */
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;
}
复制代码

2.1.4 构造函数不确定的验证

虽然构造函数、参数名称、参数类型、参数值都确定后也不一定会直接锁定构造函数,不同构造函数的参数为父子关系,所以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);
}
复制代码

2.1.5 实例化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;
}
复制代码

2.2 instantiateBean

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

/**
 * 无参的实例化bean
 */
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);
   }
}
复制代码

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

2.3 实例化策略

在上面说到有参与无参的两种讨论中,最后都是通过实例化策略构造出实例。理论上,我们已经得到足以实例化的所有相关信息,完全可以使用最简单的反射方法直接反射来构造实例化对象。我们看看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);
   }
}
复制代码

无参的实例化过程:

/**
 * 无参实例化策略
 */
@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 的配置方法,那么直接使用反射方式,简单快捷。如果使用了这两个配置,再直接使用反射的方式创建实例就不妥了,因为需要将这两个配置提供的功能切入进去,所以必须保证使用动态代理的方式将两个特性所对应的逻辑的拦截增强器设置进去,这样才能保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。

3. 记录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() 方法中没有太多处理的逻辑,除了后处理器的调用没有别的处理工作。

4. 属性注入

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

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

进入函数体:

/**
 * 对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始依赖bean
 */
@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)以及属性填充部分。

4.1 autowireByName

/**
 * 在传入的参数bw中,找出已经加载的bean,并递归实例化,进而加入到pvs中
 */
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 中。

4.2 autowireByType

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

4.3 applyPropertyValues

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

/**
 * 将所有ProtertyValues中的属性填充至BeanWrapper中
 */
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);
   }
}
复制代码

5. 初始化bean

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

exposedObject = initializeBean(beanName, exposedObject, mbd);
复制代码

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

/**
 * 初始化bean-->用户配置的init-method
 */
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;
}
复制代码

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

5.1 激活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();
   }
}
复制代码

测试结果:

hello
复制代码

测试代码中,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);
      }
   }
}
复制代码

5.2 处理器的应用

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

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

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
······
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
复制代码

中怎样实现的:

/**
 * 初始化前应用BeanPostProcessors后处理器
 */
@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获得的对象
 */
@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;
}
复制代码

5.3 激活用户自定义init方法

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

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

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

/**
 * 激活用户自定义初始化方法
 */
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);
      }
   }
}
复制代码

6. 注册DisposableBean

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

/**
 * 注册DisposableBean,销毁方法的扩展入口
 */
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 {
         // 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));
      }
   }
}
复制代码
文章分类
后端
文章标签