Spring的MergedBeanDefinition后处理器
MergedBeanDefinitionPostProcessor 是 Spring 提供的一种后处理器,它可以用于对 merged bean 进行一些操作。
它是做什么用的
我们先来看下 MergedBeanDefinitionPostProcessor 接口的定义,包括它的方法定义等,然后再看下 postProcessMergedBeanDefinition 方法是在何时回调的,以及通过它可以做什么。
接口的定义
MergedBeanDefinitionPostProcessor 类结构图如下:
MergedBeanDefinitionPostProcessor 继承自 BeanPostProcessor,相比 BeanPostProcessor 新增了 postProcessMergedBeanDefinition 和 resetBeanDefinition 两个方法,它们的定义如下:
1 | /** |
其中需要重点关注的是 postProcessMergedBeanDefinition 方法,它有 3 个入参,分别是:
RootBeanDefinition
这个其实就是 merged bean definition,是处理过 BeanDefinition 的继承关系后得到的一个最终结果
beanType
解析出来的 bean 的 class
beanName
bean 的名字
方法的回调
为了便于理解,先贴出 bean 的创建流程图(参考 AbstractAutowireCapableBeanFactory 的 doCreateBean 方法):
从图中可以看出,MergedBeanDefinitionPostProcessor 的调用是在创建完 bean 实例之后,在 populateBean 之前(这里是指的 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法回调)。
相关代码如下:
1 | if (instanceWrapper == null) { |
applyMergedBeanDefinitionPostProcessors 方法会获取所有的 MergedBeanDefinitionPostProcessor,并回调它们的 postProcessMergedBeanDefinition 方法
1 | protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { |
可以用来做什么
回调 postProcessMergedBeanDefinition 方法时,已经拿到了 merged bean definition,并且还未开始 poplateBean 填充 bean 属性、initlializeBean 初始化 bean 对象,因此可以在这里对 merged bean definition 进行一些操作,在 poplateBean 或 initlializeBean 阶段使用前面操作结果实现所需功能
在 Spring 中的应用
要了解一个功能,最直接的一个方法就是看它是怎么用的。AutowiredAnnotationBeanPostProcessor 是 MergedBeanDefinitionPostProcessor 的一个实现类,它可用于完成 Autowire 注解的依赖注入
AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor 的类结构如下图所示:
AutowiredAnnotationBeanPostProcessor 用于处理 Autowire 等依赖注入注解,它通过 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法回调获取 bean 上的 Autowire 注解,并将相关信息保存到缓存中。
1 | /** |
下面看一下相关实现的代码,它的核心是构建 metadata 信息,然后保存到缓存中。
1 | public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { |
Autowire 注解可用于 field(属性)或 method(方法),因此构建 InjectionMetadata 的代码也包含这两种使用方法的处理。
处理 filed 上的注解
1 | ReflectionUtils.doWithLocalFields(targetClass, field -> { |
它的主要流程如下:
获取类上所有的 DeclaredField
1
clazz.getDeclaredFields()
查找包含 Autowire 等依赖注入注解的 field
1
2
3
4
5
6
7
8
9
10
11private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
if (attributes != null) {
return attributes;
}
}
}
return null;
}构建 AutowiredFieldElement
1
2// 构建 autowire 元数据
currElements.add(new AutowiredFieldElement(field, required));封装为 InjectionMetadata
1
return new InjectionMetadata(clazz, elements);
处理 method 上的注解
1 | ReflectionUtils.doWithLocalMethods(targetClass, method -> { |
流程上与 field 的处理类似,主要区别是多了 BridgedMethod 的处理和方法参数的处理,结果封装为 AutowiredMethodElement 对象。
InjectedElement
InjectedElement 是一个抽象类,用于描述依赖注入元素
它的属性值如下:
1 | /** |
构造函数如下:
1 | protected InjectedElement(Member member, PropertyDescriptor pd){ |
若表示的是 filed 属性,则只需要传入 member :
InjectedElement(field, null)
若表示的是 method 方法,则还需要传入 PropertyDescriptor 表示方法参数:
InjectedElement(method, pd)
InjectedElement 的核心方法是 inject,它是通过反射注入属性值,代码如下:
1 | protected void inject(Object target, String requestingBeanName, PropertyValues pvs)throws Throwable { |
AutowiredAnnotationBeanPostProcessor 中提供了 InjectedElement 的两个实现类:AutowiredFieldElement 和 AutowiredMethodElement,分别用于 field 和 method 的 autowire 注解处理。
AutowiredFieldElement
它重写了 inject 方法,它的主要流程如下:
构造依赖描述 DependencyDescriptor
从 beanFactory 中获取依赖的 bean
1
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
注册依赖关系
1
registerDependentBeans(beanName, autowiredBeanNames);
通过反射注入属性值
相关代码如下:
1 | protected void inject(Object bean, String beanName, PropertyValues pvs)throws Throwable { |
AutowiredMethodElement
它也重写了 inject 方法,主要流程如下:
解析方法的参数类型,构造依赖描述 DependencyDescriptor
循环处理参数,从 beanFactory 中获取依赖的 bean
1
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
注册依赖关系
1
registerDependentBeans(beanName, autowiredBeans);
通过反射注入属性值
1
2ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
- 2020-04-07
Spring 提供了
@Autowired
注解,可用于自动注入所需的 bean,与 xml 配置相比更加简洁,本文主要关注@Autowired
注解的实现原理。 - 2020-04-15
dubbo 是一个流行的 RPC 框架,它提供了一个
@Reference
注解,用于配置依赖的远程接口,完成代理类的自动注入。本文主要关注@Reference
注解的实现原理。 - 2020-01-19
BeanDefinition 用来描述 spring bean,是一个接口,它的具体实现类主要有 RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition 等,分别适用于不同的场景。
- 2020-03-31
当调用 BeanFactory.getBean 方法获取 Bean 时,如果 Bean 还未创建,则会触发 Bean 的创建,本文主要关注 Bean 的创建过程。
- 2020-01-22
XmlBeanFactory 可以说是 Spring 中一个最简单的 BeanFactory,通过它可以了解 Spring 的设计思路。