在 Spring Boot 项目开发中,我们经常会遇到这样的需求:多个组件实现同一个接口,或者存在多个同类型的 Bean,但它们的执行顺序却至关重要。例如,自定义的过滤器需要按照特定顺序执行,或者多个配置类需要按先后顺序加载。Spring 提供了 @Order 注解和 Ordered 接口来解决这类排序问题。本文将结合实战案例,详细讲解如何将 @Order 注解整合到 Spring Boot 项目中,实现对 Bean 加载顺序的精确控制。

一、@Order 注解的基础用法
@Order 注解来自 Spring 核心模块,可以用在类、方法或字段上,用来声明某个组件的排序值。排序值是一个整数,数值越小,优先级越高,越先被加载或执行。如果没有显式指定 @Order,默认值为 Ordered.LOWEST_PRECEDENCE,即 Integer.MAX_VALUE,表示最低优先级。
最常见的场景是多个 Bean 实现同一个接口,而我们希望它们按照指定的顺序被注入到 List 中。例如,定义两个消息处理器,分别处理不同类型的消息,我们希望短信处理器先于邮件处理器执行。可以这样写:
// 消息处理器接口
public interface MessageHandler {
void handle(String message);
}
// 短信处理器,优先级高,先执行
@Component
@Order(1)
public class SmsMessageHandler implements MessageHandler {
@Override
public void handle(String message) {
System.out.println("处理短信消息: " + message);
}
}
// 邮件处理器,优先级低,后执行
@Component
@Order(2)
public class EmailMessageHandler implements MessageHandler {
@Override
public void handle(String message) {
System.out.println("处理邮件消息: " + message);
}
}
当我们在某个服务中注入 List<MessageHandler> 时,Spring 会自动根据 @Order 的值升序排列,短信处理器会排在邮件处理器前面。这种用法在策略模式、责任链模式中非常实用。
需要注意的是,@Order 注解也支持标注在 @Bean 方法上。例如在配置类中定义多个同类型的 Bean 时,可以在对应的方法上添加 @Order,效果与标注在类上类似。
二、深入理解 Ordered 接口与排序机制
除了 @Order 注解,Spring 还提供了 Ordered 接口,它定义了一个 getOrder() 方法,返回排序值。@Order 注解本质上是一个元注解,通过解析得到排序值,其底层同样依赖 Ordered 接口的语义。如果一个类同时实现了 Ordered 接口并标注了 @Order 注解,那么 @Order 的优先级更高(准确地说,AnnotationAwareOrderComparator 会先检查注解,再检查接口)。
Spring 内部使用 OrderComparator 和 AnnotationAwareOrderComparator 来对 Bean 进行排序。当我们在一个 Bean 中注入一个 List 或者数组类型的依赖时,如果 List 中的元素实现了 Ordered 接口或者标注了 @Order 注解,Spring 容器会自动按照 order 值进行升序排序。这个排序过程发生在依赖注入阶段,不需要我们手动干预。
实现 Ordered 接口的典型例子如下:
@Component
public class PushMessageHandler implements MessageHandler, Ordered {
@Override
public void handle(String message) {
System.out.println("处理推送消息: " + message);
}
@Override
public int getOrder() {
return 0; // 比 @Order(1) 优先级更高
}
}
在这个例子中,PushMessageHandler 实现了 Ordered 接口并返回 0,那么它将会排在所有标注了 @Order(1) 或以上的 Bean 之前。理解这个排序机制有助于我们在复杂的依赖注入场景中预测 Bean 的顺序。
三、实战:控制过滤器与拦截器的执行顺序
在实际 Web 开发中,过滤器和拦截器的执行顺序是经常需要调整的地方。Spring Boot 允许我们通过 @Order 注解或注册时设置 order 值来控制它们的先后顺序。
对于过滤器(Filter),如果我们使用 @WebFilter 注解并配合 @ServletComponentScan 扫描,可以在类上直接添加 @Order 注解。但更推荐的方式是通过 FilterRegistrationBean 来注册过滤器,并在注册时显式设置 order。例如:
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<FirstFilter> firstFilterRegistration() {
FilterRegistrationBean<FirstFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new FirstFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1); // 数字越小越先执行
return registration;
}
@Bean
public FilterRegistrationBean<SecondFilter> secondFilterRegistration() {
FilterRegistrationBean<SecondFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new SecondFilter());
registration.addUrlPatterns("/*");
registration.setOrder(2);
return registration;
}
}
对于拦截器(HandlerInterceptor),如果通过 WebMvcConfigurer 的 addInterceptors 方法注册,那么注册的顺序就是执行顺序。但如果我们需要更精细的控制,也可以在拦截器类上实现 Ordered 接口或添加 @Order 注解,然后使用 OrderedRegistry 相关机制。不过在实际项目中,大多数场景下按照注册顺序已经足够。
此外,Spring Security 的过滤器链也大量使用了 @Order,例如 @Order(SecurityProperties.BASIC_AUTH_ORDER) 等。理解 @Order 在这些组件中的作用,有助于排查过滤器顺序引发的各类问题。
四、@Order 失效场景与避坑指南
尽管 @Order 用起来很方便,但有些时候我们写了 @Order 却发现没有生效,这通常是由于以下几个原因导致的。
第一,@Order 只对 Spring 容器管理的 Bean 生效。如果组件是自己 new 出来的,或者没有通过 Spring 的扫描机制注册为 Bean,那么 @Order 自然没有任何作用。第二,在 @Configuration 类中,@Order 注解标注在配置类上并不能控制该配置类中 @Bean 方法的加载顺序,配置类的加载顺序是由 @AutoConfigureOrder 或 @AutoConfigureBefore/@AutoConfigureAfter 控制的,这两者的语义不同。第三,@Order 注解在 @Bean 方法上时,需要注意配置类的代理方式,如果使用 CGLIB 代理,@Order 注解可以被正确解析;但在某些特殊场景(如使用 @Configuration(proxyBeanMethods = false))下,可能因为不再代理而导致 @Order 失效,这时建议直接让 Bean 类实现 Ordered 接口。
另一个常见的误区是混淆 @Order 与 @Priority。@Priority 是 JSR-250 标准中的注解,Spring 也支持它进行排序,但语义略有不同:@Priority 的值越大优先级越高,与 @Order 正好相反。同时,@Priority 通常用于依赖注入时的候选 Bean 选择,而 @Order 更多用于排序。如果在同一个项目中混用这两个注解,需要特别小心,避免数值方向搞反导致顺序混乱。
五、总结与最佳实践
@Order 注解是 Spring 生态中一个轻量但强大的工具,掌握它的正确用法可以让我们的代码更加清晰、可维护。在实际项目中,建议优先使用 @Order 注解而非直接实现 Ordered 接口,因为注解更加简洁直观。如果某些 Bean 需要动态计算排序值,则可以考虑实现 Ordered 接口。
在处理过滤器、拦截器等 Web 组件时,优先使用框架提供的注册器来设置 order 值,其次是 @Order 注解。同时要注意 @Order 的作用域和代理机制的影响,避免“设了没反应”的尴尬。最后,要分清 @Order 和 @Priority 的差异,避免混用导致的逻辑错误。
通过合理整合 @Order 注解,Spring Boot 应用中的 Bean 加载顺序和组件执行顺序将变得更加可控,为构建健壮的系统打下坚实基础。
Spring Boot@Order 注解Bean 排序修改时间:2026-09-18 12:03:11