likes
comments
collection
share

Spring 源码阅读 42:AutowiredAnnotationBeanPostProcessor 分析(3)

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

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

基于 Spring Framework v5.2.6.RELEASE

接上篇:Spring 源码阅读 41:AutowiredAnnotationBeanPostProcessor 分析(2)

概述

前两篇文章分析了 AutowiredAnnotationBeanPostProcessor 后处理器的 determineCandidateConstructorspostProcessMergedBeanDefinition方法,本文分析最后一个关键的方法postProcessProperties

本文的内容非常依赖上一篇文章中的内容,因此强烈建议先阅读之前的文章。

postProcessProperties方法的调用时机,是在早期 Bean 实例被创建之后、执行属性注入之前,此时,通过调用postProcessProperties方法,可以对即将注入的属性和属性值做一些处理。

postProcessProperties方法

进入postProcessProperties方法的源码。

// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
   InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
   try {
      metadata.inject(bean, beanName, pvs);
   }
   catch (BeanCreationException ex) {
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
   }
   return pvs;
}

首先,通过findAutowiringMetadata方法获取注入元信息,这个方法在上一篇做过详细的介绍,而且,上一篇介绍的postProcessMergedBeanDefinition在此时已经被调用过了,所以,这里可以直接从缓存中获取到注入元信息。

关于注入元信息metadata中的详细内容,也可以参考上一篇文章,这里就不错做介绍了。

上一篇传送门:Spring 源码阅读 41:AutowiredAnnotationBeanPostProcessor 分析(2)

接下来,调用了metadatainject方法,并在最后将参数重传入的pvs作为方法的返回值返回。所以,这里的inject是处理逻辑的关键方法,而被处理的对象就是pvs,也就是要给 Bean 实例注入属性的属性值。

InjectionMetadata 的inject方法

我们进入inject方法。

// org.springframework.beans.factory.annotation.InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
   Collection<InjectedElement> checkedElements = this.checkedElements;
   Collection<InjectedElement> elementsToIterate =
         (checkedElements != null ? checkedElements : this.injectedElements);
   if (!elementsToIterate.isEmpty()) {
      for (InjectedElement element : elementsToIterate) {
         if (logger.isTraceEnabled()) {
            logger.trace("Processing injected element of bean '" + beanName + "': " + element);
         }
         element.inject(target, beanName, pvs);
      }
   }
}

inject方法中,首先声明了一个elementsToIterate变量,如果当前元信息对象的checkedElements成员变量不是空,那么elementsToIterate的值就是checkedElements,如果是空,则这个值是injectedElements

此处的两个集合,依然需要参考上一篇文章中介绍过的内容,这里做简单的回顾。injectedElements指的是 Spring 从当前处理的 Bean 类型中找到的所有被标记了属性注入注解的非静态的属性和方法。checkedElementsinjectedElements中被注册到相应的 BeanDefinition 的externallyManagedConfigMembers中的元素。

有了要处理的数据之后,如果elementsToIterate不为空,则遍历其中的每一个 InjectedElement 对象,进行处理。处理的逻辑在 InjectedElement 的inject方法中。

InjectedElement 的inject方法

进入inject方法。

// org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
      throws Throwable {

   if (this.isField) {
      Field field = (Field) this.member;
      ReflectionUtils.makeAccessible(field);
      field.set(target, getResourceToInject(target, requestingBeanName));
   }
   else {
      if (checkPropertySkipping(pvs)) {
         return;
      }
      try {
         Method method = (Method) this.member;
         ReflectionUtils.makeAccessible(method);
         method.invoke(target, getResourceToInject(target, requestingBeanName));
      }
      catch (InvocationTargetException ex) {
         throw ex.getTargetException();
      }
   }
}

因为每一个 InjectedElement 对象都是一个属性或者方法,这里将需要注入值的属性和方法分开处理。

如果是一个属性,则获取到对应的 Field 对象,调用field.set设置属性;如果是一个方法,则将要设置的属性值作为参数调用method.invoke执行这个方法。这样,属性注入就完成了。

在上面的方法中,不管是属性还是方法,在注入值的时候,都会通过getResourceToInject方法获取要注入的值,这个方法其实就是从 BeanFactory 容器中查找对应的 Bean 实例对象。

总结

本文介绍了 AutowiredAnnotationBeanPostProcessor 的postProcessProperties方法的源码,分析了 Spring 是如何查找通过注解注入的属性值的。至此,AutowiredAnnotationBeanPostProcessor 后处理器的源码分析就结束了。