前言
spring中有这样一个接口MergedBeanDefinitionPostProcessor,本文介绍下这个接口的作用,已经在一些源码中的使用
介绍
MergedBeanDefinitionPostProcessor接口的定义如下
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
* 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方法
@Component
public class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
System.out.println(beanName);
}
}
打断点看一下,调用链路如下
获取所有的BeanPostProcessors,如果是MergedBeanDefinitionPostProcessor,则调用它的postProcessMergedBeanDefinition方法
可见这个MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法调用的时机是,每一个spring中的bean初始化时都会经过每一个MergedBeanDefinitionPostProcessor的实现类的postProcessMergedBeanDefinition方法
源码中的使用
基于上述触发场景,这个机制大量运用于收集类的某些属性,比如spring处理@Value注解,那么是不是要在bean初始化的时候来提前收集到这些标记了@Value的字段或者方法呢?
spring @Value
AutowiredAnnotationBeanPostProcessor的定义
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
它的postProcessMergedBeanDefinition方法
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
findAutowiringMetadata方法中就是收集@Value注解的字段和方法的,以便在后面可以进行设置属性
nacos @value
NacosValueAnnotationBeanPostProcessor定义
public class NacosValueAnnotationBeanPostProcessor
extends AbstractAnnotationBeanPostProcessor implements BeanFactoryAware,
EnvironmentAware, ApplicationListener<NacosConfigReceivedEvent> {
AbstractAnnotationBeanPostProcessor 抽象类定义
public abstract class AbstractAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
NacosValueAnnotationBeanPostProcessor间接实现了MergedBeanDefinitionPostProcessor
AbstractAnnotationBeanPostProcessor在MergedBeanDefinitionPostProcessor的基础上,提供了扫描某个注解收集的实现,方便我们直接扩展,比如这里的构造方法传入NacosValue,即收集NacosValue注解
public NacosValueAnnotationBeanPostProcessor() {
super(NacosValue.class);
}
AbstractAnnotationBeanPostProcessor可以帮助我们把收集好的数据缓存在injectionMetadataCache中,以便后续处理
总结
只要是收集bean上的属性的,比如收集标记了某些注解的字段或者方法,都可以基于MergedBeanDefinitionPostProcessor来进行扩展
如:@Value、@NacosValue、mybatis的@org.apache.ibatis.annotations.Mapper等
这个MergedBeanDefinitionPostProcessor往往结合InstantiationAwareBeanPostProcessor接口配合使用,下一节讲一下InstantiationAwareBeanPostProcessor的作用