BeanFactoryPostProcessor:机制解读与代码实践

一、BeanFactoryPostProcessor 基本知识总结
1.1 核心定义与作用
BeanFactoryPostProcessor
是Spring框架中的一个关键扩展点(位于org.springframework.beans.factory.config
包),其核心功能是在Bean实例化之前修改Bean的配置元数据(即BeanDefinition)。通过该接口,开发者可以在容器启动时动态调整Bean属性(如作用域、懒加载、属性值)、注册新的Bean定义,甚至替换现有Bean的实现类
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
1.2 执行时机
- 在Spring容器加载完所有Bean定义后,Bean实例化之前(即BeanDefinition解析完成但未实例化时)触发
- 其子接口
BeanDefinitionRegistryPostProcessor
的执行时机更早,允许在Bean定义注册前进行扩展
1.3 与BeanPostProcessor的区别
对比维度 | BeanFactoryPostProcessor | BeanPostProcessor |
---|---|---|
操作对象 | BeanDefinition(Bean配置元数据) | Bean实例(已初始化对象) |
执行时机 | 容器启动时,Bean实例化前 | Bean实例化及初始化前后 |
典型应用 | 修改Bean属性、注册BeanDefinition | 代理Bean、AOP增强、属性注入后处理 |
二、BeanFactoryPostProcessor 使用姿势
2.1 修改现有 Bean 的定义
场景:动态修改Bean的作用域(如scope
)、懒加载策略(lazy-init
)、属性值等。
代码示例:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
// 修改作用域为单例
beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
// 修改属性值
MutablePropertyValues pv = beanDefinition.getPropertyValues();
pv.addPropertyValue("desc", "Modified by BeanFactoryPostProcessor");
}
}
关键类:
BeanDefinition
:存储Bean的配置元数据,如属性、作用域等。MutablePropertyValues
:提供对Bean属性值的动态修改能力 。
2.2 注册新 Bean 定义
场景:动态注册新的Bean到容器中(如基于条件动态生成Bean)。
代码示例:
@Component
public class DynamicBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
GenericBeanDefinition newDefinition = new GenericBeanDefinition();
newDefinition.setBeanClass(NewService.class);
registry.registerBeanDefinition("newService", newDefinition);
}
}
关键点:
- 使用
BeanDefinitionRegistryPostProcessor
(BeanFactoryPostProcessor 的子接口)扩展注册能力
2.3 全局配置处理
场景:统一处理所有Bean的配置(如全局设置默认值)。
代码示例:
@Component
public class GlobalConfigProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
Arrays.stream(beanFactory.getBeanDefinitionNames())
.filter(name -> beanFactory.getBeanDefinition(name).getBeanClassName().contains("Controller"))
.forEach(name -> {
BeanDefinition definition = beanFactory.getBeanDefinition(name);
definition.setLazyInit(true); // 所有Controller类设为懒加载
});
}
}
三、BeanFactoryPostProcessor 源码解析
3.1 接口源码
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
子接口扩展:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
BeanDefinitionRegistryPostProcessor 与 BeanFactoryPostProcessor关系
- 继承关系:
BeanDefinitionRegistryPostProcessor
是BeanFactoryPostProcessor
的子接口。这意味着BeanDefinitionRegistryPostProcessor
不仅拥有父接口的功能,还增加了新的能力。 - 执行顺序:在 Spring 容器启动的过程中,会先执行
BeanDefinitionRegistryPostProcessor
,之后才会执行BeanFactoryPostProcessor
。(稍后会有源码解析)
主要差异
对比维度 | BeanDefinitionRegistryPostProcessor | BeanFactoryPostProcessor |
---|---|---|
核心作用 | 能够对BeanDefinitionRegistry 进行操作,比如动态注册、修改或者删除BeanDefinition |
主要用于对ConfigurableListableBeanFactory 进行修改,像调整 bean 的属性值。 |
关键方法 | postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) |
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) |
执行时机 | 在所有标准BeanDefinition 加载完成之后,但在BeanFactoryPostProcessor 执行之前执行。 |
在所有BeanDefinition 都已经注册完成,但还没有实例化任何 bean 之前执行。 |
典型应用场景 | 实现动态注册 bean,例如 MyBatis 的MapperScannerConfigurer ;自定义注解扫描。 |
修改 bean 的定义属性,比如PropertySourcesPlaceholderConfigurer 。 |
3.2 执行原理 - 源码分析
核心入口:AbstractApplicationContext.refresh()
中的 invokeBeanFactoryPostProcessors(beanFactory)
方法。以下是关键逻辑的源码解析:
1. 源码逻辑概览
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 【本次主角】调用在上下文中注册的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 。。。
}
2. 核心处理逻辑(源码注释版)
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 【 1. 处理所有 BeanDefinitionRegistryPostProcessor(子接口)】
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
// 分阶段处理:PriorityOrdered → Ordered → 普通实现
// 执行 PriorityOrdered
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// 执行 Ordered
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
// 执行 普通实现
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 。。。
// 【 2. 处理所有 BeanFactoryPostProcessor】
// 分阶段处理:PriorityOrdered → Ordered → 普通实现
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 执行 PriorityOrdered
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 执行 Ordered
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 执行 普通实现
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 。。。
}
具体执行方法:invokeBeanFactoryPostProcessors
/**
* Invoke the given BeanFactoryPostProcessor beans.
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
// 执行具体的postProcessBeanFactory方法
postProcessor.postProcessBeanFactory(beanFactory);
}
}
四、框架级应用案例与源码解析
4.1 ConfigurationClassPostProcessor 实现原理与源码解析
ConfigurationClassPostProcessor
是 BeanDefinitionRegistryPostProcessor
的子类,负责解析 @Configuration
类及其注解(如 @ComponentScan
、@Bean
),动态注册新的 BeanDefinition
核心功能:
- 扫描配置类: 识别 @Configuration 类,解析其上的 @ComponentScan、@Import 等注解
- 处理条件注解: 根据 @Conditional 注解判断是否注册对应的 BeanDefinition
- 生成代理类: 通过 CGLIB 代理 @Configuration 类,确保 @Bean 方法返回单例对象
源码解析
入口方法:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 1. 幂等性检查(避免重复处理)
int registryId = System.identityHashCode(registry);
if (registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("重复处理配置类");
}
registriesPostProcessed.add(registryId);
// 2. 处理配置类
processConfigBeanDefinitions(registry);
}
}
核心方法 processConfigBeanDefinitions:
protected void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 。。。
// 1. 获取所有候选配置类(标记了@Configuration的Bean)
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 。。。
// 2. 解析配置类
parser.parse(candidates); // 解析@ComponentScan、@Import、@Bean等注解
// 。。。
// 3. 注册新的BeanDefinition
this.reader.loadBeanDefinitions(configClasses); // 将解析结果注册到容器
}
4.2 PropertySourcesPlaceholderConfigurer 实现原理与源码解析
PropertySourcesPlaceholderConfigurer
是 Spring 中用于解析属性占位符(如 ${jdbc.url}
)的 BeanFactoryPostProcessor
实现类。其核心功能是在 Bean 实例化前,将配置文件中的占位符替换为实际值
工作流程:
- 加载属性源: 从环境变量、
@PropertySource
注解指定的文件、系统属性等来源收集键值对,合并到MutablePropertySources
中 - 递归解析占位符: 遍历所有
BeanDefinition
,通过BeanDefinitionVisitor
替换${...}
占位符为实际值,支持嵌套占位符(如${outer.${inner.key}}
)
源码解析
入口方法:
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 。。。
processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
// 。。。
}
/**
* Visit each bean definition in the given bean factory and attempt to replace ${...} property
* placeholders with values from the given properties.
*/
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
final ConfigurablePropertyResolver propertyResolver) throws BeansException {
// "${"
propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
// "}"
propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
// ":"
propertyResolver.setValueSeparator(this.valueSeparator);
// 。。。
// 执行具体解析逻辑
doProcessProperties(beanFactoryToProcess, valueResolver);
}
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
StringValueResolver valueResolver) {
// 。。。
// 具体解析逻辑
beanFactoryToProcess.resolveAliases(valueResolver);
// 具体解析逻辑
beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}
五、高频面试题与解析
5.1 什么是 BeanFactoryPostProcessor?它的作用是什么?
BeanFactoryPostProcessor
是 Spring 容器初始化过程中的一个扩展点,允许开发者在 Bean 定义加载完成后、Bean 实例化之前修改 BeanDefinition
。其核心方法是:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
典型应用:
- 修改
BeanDefinition
的属性值(如替换占位符) - 注册额外的
BeanDefinition
- 调整 Bean 的作用域或懒加载特性
5.2 BeanFactoryPostProcessor与BeanPostProcessor的区别?
BeanFactoryPostProcessor
:操作BeanDefinition
,在Bean实例化前执行BeanPostProcessor
:操作Bean实例,在Bean初始化前后执行(如@PostConstruct
、AOP
代理)
5.3 如何自定义一个 BeanFactoryPostProcessor?请举例说明。
自定义步骤:
- 实现
BeanFactoryPostProcessor
接口,重写postProcessBeanFactory
方法。 - 在方法中通过
beanFactory.getBeanDefinition("beanName")
获取并修改BeanDefinition
。
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("myBean");
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); // 修改作用域为原型
bd.getPropertyValues().add("age", 18); // 添加属性值
}
}
5.4 BeanFactoryPostProcessor的执行顺序如何控制?
- 实现
Ordered
接口:重写getOrder()
方法返回优先级值(越小越优先)。 - 使用
@Order
注解:指定优先级值
5.5 为什么 PropertySourcesPlaceholderConfigurer 是 BeanFactoryPostProcessor 的典型实现?
PropertySourcesPlaceholderConfigurer
用于解析配置文件中的占位符,如${db.url}
。它在 Bean 实例化前,读取配置源,将BeanDefinition中的占位符替换为实际值,本质是修改BeanDefinition的属性值,所以是BeanFactoryPostProcessor
的典型应用。