Spring 源码阅读 42:AutowiredAnnotationBeanPostProcessor 分析(3)
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
基于 Spring Framework v5.2.6.RELEASE
接上篇:Spring 源码阅读 41:AutowiredAnnotationBeanPostProcessor 分析(2)
概述
前两篇文章分析了 AutowiredAnnotationBeanPostProcessor 后处理器的 determineCandidateConstructors
和postProcessMergedBeanDefinition
方法,本文分析最后一个关键的方法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)
接下来,调用了metadata
的inject
方法,并在最后将参数重传入的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 类型中找到的所有被标记了属性注入注解的非静态的属性和方法。checkedElements
是injectedElements
中被注册到相应的 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 后处理器的源码分析就结束了。
- Spring 源码阅读 42:AutowiredAnnotationBeanPostProcessor 分析(3)
- Spring 源码阅读 41:AutowiredAnnotationBeanPostProcessor 分析(2)
- Kafka 消费者组 Rebalance 详细过程
- Spring 源码阅读 01:Resource 资源抽象
- 初识机器学习:回归分析
- 初识机器学习:Louvain 社区发现算法
- 初识机器学习:关联规则
- 使用 Redis 实现分布式锁的方法
- Kafka 目录里的脚本那么多,它们都是用来干什么的?
- Kafka 消费者组位移重设的几种方式
- LeetCode - 84. 柱状图中最大的矩形
- LeetCode - 22. 括号生成