SpringBoot项目中对定义的多个BeanPostProcessor排序
前言
BeanPostProcessor 是 Spring 提供的一种扩展机制,可以让我们在 bean 初始化前后做一些额外的操作,Spring 中的 @Async,@Scheduled,@RabbitHandler 等注解的底层实现都是 BeanPostProcessor 在起作用,如 RabbitListenerAnnotationBeanPostProcessor。
代码示例
@Configuration
public class BeanPostProcessorConfig2 {
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public static class UserServiceBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof UserService) {
System.out.println("UserService");
}
return bean;
}
}
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public static class UserServiceBeanPostProcessor2 implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof UserService) {
System.out.println("UserService2");
}
return bean;
}
}
@Component
public static class UserService {
}
@Component
public static class OrderService {
}
}
这里我们定义了两个 BeanPostProcessor,第二个优先级更高,但优先级设置没生效,还是先打印了 UserService。
原因分析
- AbstractApplicationContext 在 refresh() 方法内会处理 BeanPostProcessor,具体方法为 registerBeanPostProcessors()。
- 进入 registerBeanPostProcessors() 方法
- 再进入 PostProcessorRegistrationDelegate 的 registerBeanPostProcessors() 方法
- 可以看到,Spring 只会处理 实现 Ordered 接口或 PriorityOrdered 接口的 BeanPostProcessor(不支持 @Order 注解)。
- 最终使用的比较器为 AnnotationAwareOrderComparator(它是支持 @Order 注解的),但因为上一步已经将 @Order 注解的排除掉了,所以也不会生效。
解决方法
不使用 @Order 注解来设置优先级,使用 Ordered 接口或 PriorityOrdered 接口。
扩展
BeanFactoryPostProcessor 也是和 BeanPostProcessor 同样的逻辑,但 BeanDefinitionRegistryPostProcessor 不一样,@Order 注解, Ordered 接口和 PriorityOrdered 接口都支持。