BeanPostProcessor vs BeanFactoryPostProcessor:两个扩展点的执行时机
BeanPostProcessor vs BeanFactoryPostProcessor:两个扩展点的执行时机
适读人群:Spring中级到高级开发者,需要深度定制Bean创建流程的架构师 | 阅读时长:约18分钟
开篇故事
刚开始学Spring的时候,我把这两个接口搞混了好多次。BeanPostProcessor和BeanFactoryPostProcessor,名字相似,但操作的对象完全不同,执行时机差了好几个阶段。
有一次我在BeanFactoryPostProcessor里调用了beanFactory.getBean(),拿一个业务Bean来做某些注册操作。代码本地跑得好好的,上了测试环境报了一个莫名其妙的错:某个Bean的AOP代理没生效,直接拿到的是裸对象。
排查了半天才发现原因:在BeanFactoryPostProcessor执行阶段,BeanPostProcessor还没有注册,这时候调用getBean()会绕过所有BeanPostProcessor(包括AOP代理),拿到的是没有任何增强的原始对象,并且这个对象会被缓存。后续通过正常方式再拿,得到的依然是那个无代理的对象。
这个坑让我对这两个接口的执行时机有了深刻的记忆。
一、两个接口的定位
BeanFactoryPostProcessor:操作的是BeanFactory(Bean工厂),在Bean定义加载完毕、Bean实例创建之前执行。可以修改BeanDefinition,但不应该触发Bean实例化。
BeanPostProcessor:操作的是Bean实例,在每个Bean实例化之后执行。可以对实例进行后处理(包装、代理等)。
| 维度 | BeanFactoryPostProcessor | BeanPostProcessor |
|---|---|---|
| 操作对象 | BeanFactory/BeanDefinition | Bean实例 |
| 执行时机 | Bean实例化之前 | 每个Bean实例化后 |
| 实例数 | 每个实现类执行一次 | 每个Bean都会经过所有BPP |
| 典型用途 | 修改BeanDefinition、注册新Bean | AOP代理、注解处理 |
二、源码核心路径解析
2.1 执行顺序全景图
2.2 invokeBeanFactoryPostProcessors的执行顺序
这个方法的逻辑相当复杂,涉及BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor两层,以及PriorityOrdered、Ordered、无Order三档排序:
// PostProcessorRegistrationDelegate.java(Spring Framework 6.x)
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory,
List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry registry) {
// 第一轮:处理BeanDefinitionRegistryPostProcessor
// 优先级:1. 手动注册的 2. PriorityOrdered 3. Ordered 4. 其他
// 注意:每一轮处理后,可能又有新的BDRPP被注册进来,需要循环处理
// 手动注册的BDRPP(通过addBeanFactoryPostProcessor方式)
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor pp : beanFactoryPostProcessors) {
if (pp instanceof BeanDefinitionRegistryPostProcessor rpp) {
rpp.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(rpp);
}
}
// 从BeanFactory获取PriorityOrdered的BDRPP(首先是ConfigurationClassPostProcessor)
String[] postProcessorNames = beanFactory.getBeanNamesForType(
BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors =
new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(
beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 执行ConfigurationClassPostProcessor(扫描@Component、处理@Configuration等)
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry, ...);
// ... 继续处理Ordered和无Order的BDRPP
// 循环直到没有新的BDRPP被注册
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(
BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
// 新发现的BDRPP,执行它
// ...
reiterate = true;
}
}
}
// 第二轮:对所有BDRPP调用postProcessBeanFactory
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
}
// 第三轮:处理普通BeanFactoryPostProcessor(非BDRPP)
// 同样按PriorityOrdered -> Ordered -> 无Order的顺序
// ...
}2.3 BeanPostProcessor的执行流程
// AbstractAutowireCapableBeanFactory.java doCreateBean方法(简化)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd,
Object[] args) throws BeanCreationException {
// 1. 实例化(调用构造方法)
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
// 2. 允许BeanPostProcessor修改合并后的BeanDefinition
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// 3. 提前暴露单例引用(解决循环依赖)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// 4. 填充属性(@Autowired注入)
populateBean(beanName, mbd, instanceWrapper);
// 5. 初始化
Object exposedObject = initializeBean(beanName, bean, mbd);
return exposedObject;
}
protected Object initializeBean(String beanName, Object bean,
@Nullable RootBeanDefinition mbd) {
// 5.1 调用Aware接口
invokeAwareMethods(beanName, bean);
// 5.2 BeanPostProcessor.postProcessBeforeInitialization
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 5.3 调用init方法(@PostConstruct已在BPP中处理)
invokeInitMethods(beanName, wrappedBean, mbd);
// 5.4 BeanPostProcessor.postProcessAfterInitialization(AOP代理在这里)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}三、完整代码示例
3.1 BeanFactoryPostProcessor:批量修改BeanDefinition
// 用途:把所有@Service的Bean的scope改为prototype(演示用,实际别这样做)
@Component
public class ScopeModifierBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
PriorityOrdered {
private static final Logger log =
LoggerFactory.getLogger(ScopeModifierBeanFactoryPostProcessor.class);
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 在这里,所有BeanDefinition已加载,但Bean还没有实例化
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
// 检查是否有@Service注解(通过AnnotatedBeanDefinition)
if (bd instanceof AnnotatedBeanDefinition abd) {
AnnotationMetadata metadata = abd.getMetadata();
if (metadata.hasAnnotation("org.springframework.stereotype.Service")) {
// 在这里可以安全地修改BeanDefinition
// 注意:不要在这里调用beanFactory.getBean()!
String originalScope = bd.getScope();
log.info("Bean {} scope: {}", beanName,
originalScope.isEmpty() ? "singleton" : originalScope);
}
}
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE; // 最后执行,避免影响ConfigurationClassPostProcessor
}
}
// 更实用的用途:替换配置中的加密占位符
@Component
public class PropertyDecryptBeanFactoryPostProcessor
implements BeanFactoryPostProcessor, PriorityOrdered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 修改PropertyPlaceholderConfigurer或Environment中的加密属性
if (beanFactory instanceof ConfigurableListableBeanFactory clbf) {
// 处理Bean定义中的PropertyValues
for (String beanName : clbf.getBeanDefinitionNames()) {
BeanDefinition bd = clbf.getBeanDefinition(beanName);
processPropertyValues(bd.getPropertyValues());
}
}
}
private void processPropertyValues(MutablePropertyValues pvs) {
for (PropertyValue pv : pvs.getPropertyValues()) {
Object value = pv.getValue();
if (value instanceof String strVal && strVal.startsWith("ENC(")) {
String decrypted = decrypt(strVal.substring(4, strVal.length() - 1));
pvs.add(pv.getName(), decrypted);
}
}
}
private String decrypt(String encrypted) {
// 实际解密逻辑
return new String(Base64.getDecoder().decode(encrypted));
}
@Override
public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; }
}3.2 BeanPostProcessor:自动埋点的AOP-like实现
// 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Monitored {
String metricName() default "";
}
// 自定义BeanPostProcessor,为所有有@Monitored注解的Bean创建代理
@Component
public class MonitoredBeanPostProcessor implements BeanPostProcessor {
@Autowired
private MeterRegistry meterRegistry;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
Class<?> targetClass = AopUtils.getTargetClass(bean);
// 检查该类是否有任何方法上有@Monitored注解
boolean hasMonitoredMethods = Arrays.stream(targetClass.getMethods())
.anyMatch(m -> m.isAnnotationPresent(Monitored.class));
if (!hasMonitoredMethods) {
return bean; // 没有@Monitored,直接返回原Bean
}
// 创建JDK动态代理(如果实现了接口)或CGLIB代理
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.addAdvice((MethodInterceptor) invocation -> {
Method method = invocation.getMethod();
Monitored monitored = method.getAnnotation(Monitored.class);
if (monitored == null) {
return invocation.proceed();
}
String metricName = monitored.metricName().isEmpty() ?
targetClass.getSimpleName() + "." + method.getName() :
monitored.metricName();
Timer timer = meterRegistry.timer(metricName);
return timer.recordCallable(invocation::proceed);
});
return proxyFactory.getProxy();
}
}
// 使用示例
@Service
public class OrderService {
@Monitored(metricName = "order.create")
public Order createOrder(CreateOrderRequest request) {
// 方法执行时间会被自动记录到Micrometer
return orderRepository.save(Order.from(request));
}
@Monitored // 默认metricName = "OrderService.findById"
public Optional<Order> findById(Long id) {
return orderRepository.findById(id);
}
}四、踩坑实录
坑1:在BeanFactoryPostProcessor中调用getBean导致AOP失效
这是开篇提到的坑,根本原因在源码里很清楚:
// AbstractBeanFactory.java getBean时机判断(简化)
// 当BeanFactoryPostProcessor执行时,BPP还没注册
// 调用getBean会走正常实例化流程,但BPP为空
// 导致:@Transactional、@Async等AOP代理都没有!
// 错误:
@Component
public class BadBFPP implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
UserService us = beanFactory.getBean(UserService.class); // 裸对象!无AOP
us.doSomething(); // @Transactional不生效
}
}
// 正确:如果必须用某个Bean,把操作推迟到ApplicationRunner
@Component
public class StartupTask implements ApplicationRunner {
@Autowired
private UserService userService; // 正确时机获取,有AOP代理
@Override
public void run(ApplicationArguments args) {
userService.doSomething(); // @Transactional正常生效
}
}坑2:自定义BeanPostProcessor本身也被BPP处理
BeanPostProcessor本身也是Spring管理的Bean,但它们在初始化时享有特殊的早期实例化流程(在registerBeanPostProcessors阶段)。如果你的BeanPostProcessor依赖了某个业务Bean,而业务Bean也依赖你,可能触发循环初始化问题。
Spring会打印警告:Bean 'xxx' of type [...] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
意思是:这个Bean在BPP完全注册之前就被实例化了,某些BPP没有机会处理它。
坑3:BeanPostProcessor的postProcessAfterInitialization返回null
// 错误:返回null会导致Spring抛出NullPointerException
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (someCondition) {
return wrapBean(bean);
}
return null; // 错误!应该返回原bean
}
// 正确:不需要处理时返回原bean
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (someCondition) {
return wrapBean(bean);
}
return bean; // 返回原bean
}坑4:BeanDefinitionRegistryPostProcessor执行多次
BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry可能被调用多次(因为新注册的BDRPP会触发重新遍历)。如果你在实现里有副作用(比如计数、写文件),要做幂等处理。
五、总结与延伸
一张图总结执行时机:
扫描BeanDefinition → [BeanDefinitionRegistryPostProcessor执行]
→ [BeanFactoryPostProcessor执行]
→ 注册BeanPostProcessor
→ 实例化每个Bean
→ [BeanPostProcessor.beforeInit]
→ afterPropertiesSet/init-method
→ [BeanPostProcessor.afterInit](AOP代理在这里)记住核心原则:
BeanFactoryPostProcessor:改元数据,不碰实例BeanPostProcessor:改实例,每个Bean都会经过
下一篇我们聊Spring Boot的外部化配置,18种PropertySource的加载顺序,这是生产部署必须掌握的知识。
