Spring的MergedBeanDefinition后处理器

MergedBeanDefinitionPostProcessor 是 Spring 提供的一种后处理器,它可以用于对 merged bean 进行一些操作。

它是做什么用的

我们先来看下 MergedBeanDefinitionPostProcessor 接口的定义,包括它的方法定义等,然后再看下 postProcessMergedBeanDefinition 方法是在何时回调的,以及通过它可以做什么。

接口的定义

MergedBeanDefinitionPostProcessor 类结构图如下:

image-20200405111349686

MergedBeanDefinitionPostProcessor 继承自 BeanPostProcessor,相比 BeanPostProcessor 新增了 postProcessMergedBeanDefinition 和 resetBeanDefinition 两个方法,它们的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Post-process the given merged bean definition for the specified bean.
* @param beanDefinition the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance.
* @param beanName the name of the bean
* @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

/**
* A notification that the bean definition for the specified name has been reset,
* and that this post-processor should clear any metadata for the affected bean.
* <p>The default implementation is empty.
* @param beanName the name of the bean
* @since 5.1
* @see DefaultListableBeanFactory#resetBeanDefinition
*/
default void resetBeanDefinition(String beanName) {
}

其中需要重点关注的是 postProcessMergedBeanDefinition 方法,它有 3 个入参,分别是:

  1. RootBeanDefinition

    这个其实就是 merged bean definition,是处理过 BeanDefinition 的继承关系后得到的一个最终结果

  2. beanType

    解析出来的 bean 的 class

  3. beanName

    bean 的名字

方法的回调

为了便于理解,先贴出 bean 的创建流程图(参考 AbstractAutowireCapableBeanFactory 的 doCreateBean 方法):

image-20200402015737100

从图中可以看出,MergedBeanDefinitionPostProcessor 的调用是在创建完 bean 实例之后,在 populateBean 之前(这里是指的 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法回调)。

相关代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if (instanceWrapper == null) {
// 创建 java bean 并封装到 beanWrapper 中,执行完 beanWrapper 的初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}

// 这里就可以拿到 bean 实例和对应的 bean class
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();

if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 回调 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法
// 这里要用到上一步得到 beanType 作为入参
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

applyMergedBeanDefinitionPostProcessors 方法会获取所有的 MergedBeanDefinitionPostProcessor,并回调它们的 postProcessMergedBeanDefinition 方法

1
2
3
4
5
6
7
8
9
10
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
// getBeanPostProcessors 用于获取所有的 BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
// 回调 postProcessMergedBeanDefinition 方法
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}

可以用来做什么

回调 postProcessMergedBeanDefinition 方法时,已经拿到了 merged bean definition,并且还未开始 poplateBean 填充 bean 属性、initlializeBean 初始化 bean 对象,因此可以在这里对 merged bean definition 进行一些操作,在 poplateBean 或 initlializeBean 阶段使用前面操作结果实现所需功能

image-20200405120453417

在 Spring 中的应用

要了解一个功能,最直接的一个方法就是看它是怎么用的。AutowiredAnnotationBeanPostProcessor 是 MergedBeanDefinitionPostProcessor 的一个实现类,它可用于完成 Autowire 注解的依赖注入

AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor 的类结构如下图所示:

image-20200405120908698

AutowiredAnnotationBeanPostProcessor 用于处理 Autowire 等依赖注入注解,它通过 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法回调获取 bean 上的 Autowire 注解,并将相关信息保存到缓存中。

1
2
3
4
5
6
/**
* AutowiredAnnotationBeanPostProcessor 的属性,用于保存解析出来的依赖注入元信息
* key: 用于表示 bean,例如可以是 beanName
* value: 解析出来的依赖注入配置
*/
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);

下面看一下相关实现的代码,它的核心是构建 metadata 信息,然后保存到缓存中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// annotation 依赖注入:查找 bean 上配置的依赖注入注解配置,并缓存起来
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 构建 autowire 的元数据,包括 field 和 method
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}

Autowire 注解可用于 field(属性)或 method(方法),因此构建 InjectionMetadata 的代码也包含这两种使用方法的处理。

处理 filed 上的注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 查找字段上的 autowire 注解
AnnotationAttributes 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);

// 构建 autowire 元数据
currElements.add(new AutowiredFieldElement(field, required));
}
});

它的主要流程如下:

  1. 获取类上所有的 DeclaredField

    1
    clazz.getDeclaredFields()
  2. 查找包含 Autowire 等依赖注入注解的 field

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    private 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;
    }
  3. 构建 AutowiredFieldElement

    1
    2
    // 构建 autowire 元数据
    currElements.add(new AutowiredFieldElement(field, required));
  4. 封装为 InjectionMetadata

    1
    return new InjectionMetadata(clazz, elements);

处理 method 上的注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// 查找方法上的 autowire 注解
AnnotationAttributes 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
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);

// 构建 autowire 元数据
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});

流程上与 field 的处理类似,主要区别是多了 BridgedMethod 的处理和方法参数的处理,结果封装为 AutowiredMethodElement 对象。

InjectedElement

InjectedElement 是一个抽象类,用于描述依赖注入元素

image-20200405175133978

它的属性值如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 依赖注入的目标,可以是构造函数、setter、field
*/
protected final Member member;

/**
* 是否为 field
*/
protected final boolean isField;

/**
* 属性描述
*/
@Nullable
protected final PropertyDescriptor pd;

/**
* 标记依赖注入属性是否需要跳过
*/
@Nullable
protected volatile Boolean skip;

构造函数如下:

1
2
3
4
5
protected InjectedElement(Member member, @Nullable PropertyDescriptor pd) {
this.member = member;
this.isField = (member instanceof Field);
this.pd = pd;
}
  • 若表示的是 filed 属性,则只需要传入 member :InjectedElement(field, null)

  • 若表示的是 method 方法,则还需要传入 PropertyDescriptor 表示方法参数:InjectedElement(method, pd)

InjectedElement 的核心方法是 inject,它是通过反射注入属性值,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
if (this.isField) {
// field 依赖注入
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
// method 依赖注入
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}

AutowiredAnnotationBeanPostProcessor 中提供了 InjectedElement 的两个实现类:AutowiredFieldElement 和 AutowiredMethodElement,分别用于 field 和 method 的 autowire 注解处理。

AutowiredFieldElement

它重写了 inject 方法,它的主要流程如下:

  1. 构造依赖描述 DependencyDescriptor

  2. 从 beanFactory 中获取依赖的 bean

    1
    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
  3. 注册依赖关系

    1
    registerDependentBeans(beanName, autowiredBeanNames);
  4. 通过反射注入属性值

相关代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
// 构造依赖描述
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());

Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 从 beanFactory 中获取依赖的 bean
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;

// 注册依赖关系
registerDependentBeans(beanName, autowiredBeanNames);

if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();

if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 添加到缓存中
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
// 通过反射注入属性值
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}

AutowiredMethodElement

它也重写了 inject 方法,主要流程如下:

  1. 解析方法的参数类型,构造依赖描述 DependencyDescriptor

  2. 循环处理参数,从 beanFactory 中获取依赖的 bean

    1
    Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
  3. 注册依赖关系

    1
    registerDependentBeans(beanName, autowiredBeans);
  4. 通过反射注入属性值

    1
    2
    ReflectionUtils.makeAccessible(method);
    method.invoke(bean, arguments);