在上一篇我们分析了@Autowirde的来龙去脉,主要围绕AutowiredAnnotationBeanPostProcessor怎么来的,什么时候执行来展开的,留了一个尾巴,就是spring是如何识别被@Autowirde修饰的方法的,依赖注入又是怎么注入的,这次尝试来弄明白这个过程。
有了上回的基础,直接到populateBean方法中找到BPP的postProcessProperties方法进行分析
我们的主角依旧是AutowiredAnnotationBeanPostProcessor,因为间接的实现了InstantiationAwareBeanPostProcessor,故而这里实际调用的是主角的postProcessProperties
元信息识别
上来先找到注解元信息findAutowiringMetadata
怎么找的,和getBean类似,先从缓存中找,找不到再去构建
仔细看看是如何构建的,如果没有,直接返回空,否则分两类,一类是被Autowirde修饰的属性,一类是Autowirde被修饰的方法,分别处理
看一下它这个判断是否有注解的代码autowiredAnnotationTypes,其实不止包含Autowirde
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {// 判断是否有注解
return InjectionMetadata.EMPTY;
}
包含Autowired、Value两个基本的,还可以包含jakarta.inject.Inject包下的Inject以及javax.inject.Inject包下的Inject
先看看是如何处理属性的,用的是一个反射工具类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)
简单总结一下,就通过反射机制识别被@Autowired、@Value、@Inject标注了的属性或方法,将属性和方法的基本信息封装起来
注入
注解元信息获取后,就是开始注入
循环遍历需要注入的元素
如果是属性,最终还是通过反射的方式进行set的
如果是方法,也是反射,只是调用的是invoke实现的
总结
这次主要探究了@Autowirde注解是如何被识别和注入是如何实现的——反射
无论是注解的识别还是属性的注入都是依赖反射来实现的
所以反射是个非常非常重要非常非常基础的技术栈,必须无条件掌握
留坑
时间有限,没有继续深挖,比如注解元信息是怎么转换成我们要的对象的,如果是熟悉重点就在resolveFieldValue
如果是方法,就在resolveMethodArguments
这个坑,下次再填。