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

原因分析

  1. AbstractApplicationContext 在 refresh() 方法内会处理 BeanPostProcessor,具体方法为 registerBeanPostProcessors()。
  2. 进入 registerBeanPostProcessors() 方法
  3. 再进入 PostProcessorRegistrationDelegate 的 registerBeanPostProcessors() 方法
  4. 可以看到,Spring 只会处理 实现 Ordered 接口或 PriorityOrdered 接口的 BeanPostProcessor(不支持 @Order 注解)。
  5. 最终使用的比较器为 AnnotationAwareOrderComparator(它是支持 @Order 注解的),但因为上一步已经将 @Order 注解的排除掉了,所以也不会生效。

解决方法

不使用 @Order 注解来设置优先级,使用 Ordered 接口或 PriorityOrdered 接口。

扩展

BeanFactoryPostProcessor 也是和 BeanPostProcessor 同样的逻辑,但 BeanDefinitionRegistryPostProcessor 不一样,@Order 注解, Ordered 接口和 PriorityOrdered 接口都支持。

posted @ 2024-04-14 13:10  strongmore  阅读(128)  评论(0编辑  收藏  举报