spring 的后置处理器是 spring 生态得以繁荣的一个重要基础, 大量流行的框架都使用了各种类型的 PostProcessor 增强了自身的能力, 并为开发者提供了无数便利;

BeanDefinition 的后置处理

两种 BeanFactory 处理器对比

BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 是 Spring 框架中用于在容器启动过程中对 Bean 定义进行扩展和修改的两个重要接口, 它们的主要区别在于作用时机和功能范围;

BeanFactoryPostProcessor

BeanFactoryPostProcessor 是 Spring 提供的一个接口,允许在 Spring 容器实例化 Bean 之前对 BeanDefinition 进行修改; 它主要用于在容器加载 Bean 定义之后、实例化 Bean 之前,对 Bean 定义进行全局的修改或扩展;

使用场景:

  • 修改 Bean 定义:例如,修改 Bean 的属性值、添加新的属性、修改 Bean 的作用域等。
  • 动态注册 Bean:虽然 BeanFactoryPostProcessor 本身不能直接注册新的 Bean,但可以通过获取 BeanFactory 来间接实现。
  • 配置文件的处理:例如,解析自定义的配置文件并将其转换为 Spring 的 Bean 定义。

举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改 Bean 定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("myBean");
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}

BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口,它在 BeanFactoryPostProcessor 的基础上提供了更早的扩展点。它允许在 Spring 容器加载 Bean 定义的过程中,直接操作 BeanDefinitionRegistry,从而可以动态注册、修改或删除 Bean 定义;

使用场景:

  • 动态注册 Bean:在容器启动时,根据某些条件动态注册新的 Bean 定义。
  • 修改或删除 Bean 定义:在 Bean 定义加载到容器之前,对已有的 Bean 定义进行修改或删除。
  • 与 BeanFactoryPostProcessor 结合使用:在 BeanFactoryPostProcessor 之前执行,确保在 Bean 定义加载的早期阶段进行干预。

举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 动态注册一个新的 Bean 定义
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyBean.class);
registry.registerBeanDefinition("myDynamicBean", beanDefinition);
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 可以在这里对 BeanFactory 进行进一步的处理
}
}

对比总结

特性 BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor
作用时机 在 Bean 定义加载之后、Bean 实例化之前 在 Bean 定义加载过程中,比 BeanFactoryPostProcessor 更早
功能范围 只能修改已有的 Bean 定义 可以动态注册、修改或删除 Bean 定义
继承关系 是 BeanDefinitionRegistryPostProcessor 的父接口 是 BeanFactoryPostProcessor 的子接口
使用场景 修改 Bean 定义、处理配置文件 动态注册 Bean、修改或删除 Bean 定义

使用建议:

  • 如果你只需要修改已有的 Bean 定义,使用 BeanFactoryPostProcessor 即可。
  • 如果你需要在 Bean 定义加载的过程中动态注册新的 Bean 或对 Bean 定义进行更早的干预,使用 BeanDefinitionRegistryPostProcessor

通过合理使用这两个接口,可以在 Spring 容器启动过程中对 Bean 定义进行灵活的扩展和定制;

加载与执行时机

PostProcessorRegistrationDelegate

1
2
3
4
AbstractApplicationContext:
refresh() -> invokeBeanFactoryPostProcessors(beanFactory)
PostProcessorRegistrationDelegate:
invokeBeanFactoryPostProcessors(beanFactory, beanFactoryPostProcessors)

先处理参数传进来的 beanFactoryPostProcessors:

1
foreach processor in beanFactoryPostProcessors:

然后处理已注册到 beanDefinitionRegistry 的 custom beanFactoryPostProcessors:

1
2
3
4
5
6
// 从 registry 找出所有已注册的 beanFactoryPostProcessor 的 beanName
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 优先处理

BeanFactoryPostProcessor:
postProcessBeanFactory(beanFactory)

经典应用场景

mybatis-spring

placeHolder 占位符替换

Bean 实例的后置处理

BeanPostProcessor