spring是如何怎么识别被@Autowirde修饰的属性的,又是如何实现属性注入的?

156 阅读3分钟

书接上回:Spring中@Autowired注解装配流程

在上一篇我们分析了@Autowirde的来龙去脉,主要围绕AutowiredAnnotationBeanPostProcessor怎么来的,什么时候执行来展开的,留了一个尾巴,就是spring是如何识别被@Autowirde修饰的方法的,依赖注入又是怎么注入的,这次尝试来弄明白这个过程。

有了上回的基础,直接到populateBean方法中找到BPP的postProcessProperties方法进行分析

image.png

我们的主角依旧是AutowiredAnnotationBeanPostProcessor,因为间接的实现了InstantiationAwareBeanPostProcessor,故而这里实际调用的是主角的postProcessProperties

image.png

元信息识别

上来先找到注解元信息findAutowiringMetadata

image.png

怎么找的,和getBean类似,先从缓存中找,找不到再去构建

image.png

仔细看看是如何构建的,如果没有,直接返回空,否则分两类,一类是被Autowirde修饰的属性,一类是Autowirde被修饰的方法,分别处理

image.png

看一下它这个判断是否有注解的代码autowiredAnnotationTypes,其实不止包含Autowirde

if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {// 判断是否有注解
   return InjectionMetadata.EMPTY;
}

包含Autowired、Value两个基本的,还可以包含jakarta.inject.Inject包下的Inject以及javax.inject.Inject包下的Inject

image.png

先看看是如何处理属性的,用的是一个反射工具类ReflectionUtils


ReflectionUtils.doWithLocalFields(targetClass, field -> {//利用反射工具找所有标注了Autowirde的属性
   MergedAnnotation<?> ann = findAutowiredAnnotation(field);
   if (ann != null) {
      if (Modifier.isStatic(field.getModifiers())) {
         if (logger.isInfoEnabled()) {
            logger.info("Autowired annotation is not supported on static fields: " + field);
         }
         return;
      }
      boolean required = determineRequiredStatus(ann);
      currElements.add(new AutowiredFieldElement(field, required));
   }
});

处理方法也类似,也是利用反射工具类ReflectionUtils来实现的。

ReflectionUtils.doWithLocalMethods(targetClass, method -> {//利用反射工具找所有标注了Autowirde的方法
   Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
   if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
      return;
   }
   MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
   if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
      if (Modifier.isStatic(method.getModifiers())) {
         if (logger.isInfoEnabled()) {
            logger.info("Autowired annotation is not supported on static methods: " + method);
         }
         return;
      }
      if (method.getParameterCount() == 0) {
         if (logger.isInfoEnabled()) {
            logger.info("Autowired annotation should only be used on methods with parameters: " +
                  method);
         }
      }
      boolean required = determineRequiredStatus(ann);
      PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
      currElements.add(new AutowiredMethodElement(method, required, pd));
   }
});

识别出来被注解标注过的不管是方法还是属性,都封装在AutowiredFieldElement中,然后统一添加到InjectedElement中,最后封装成InjectionMetadata供后续步骤使用。

InjectionMetadata.forElements(elements, clazz)

image.png

简单总结一下,就通过反射机制识别被@Autowired、@Value、@Inject标注了的属性或方法,将属性和方法的基本信息封装起来

注入

注解元信息获取后,就是开始注入

image.png

循环遍历需要注入的元素

image.png

如果是属性,最终还是通过反射的方式进行set的

image.png

如果是方法,也是反射,只是调用的是invoke实现的

image.png

总结

这次主要探究了@Autowirde注解是如何被识别和注入是如何实现的——反射

无论是注解的识别还是属性的注入都是依赖反射来实现的

所以反射是个非常非常重要非常非常基础的技术栈,必须无条件掌握

留坑

时间有限,没有继续深挖,比如注解元信息是怎么转换成我们要的对象的,如果是熟悉重点就在resolveFieldValue

image.png 如果是方法,就在resolveMethodArguments

image.png

这个坑,下次再填。