在 Spring Boot 项目中,组件加载和执行顺序看似由容器自动决定,实际上可以通过排序机制进行控制。需要明确指定多个过滤器、拦截器或者自动配置类的先后关系时,如果对排序规则不熟悉,很容易出现安全校验被跳过、数据源初始化晚于业务 Bean 等问题。本文围绕 @Order 注解、Ordered 接口以及 Spring Boot 自动配置顺序展开。

一、Spring Boot 中的顺序控制机制
首先要澄清一个容易混淆的概念:Spring Boot 并没有名为 @EnableOrder 的注解。开启排序能力并不需要引入某个开关,而是直接使用 @Order 注解或实现 Ordered 接口。@Order 可以标注在组件类、@Bean 方法以及部分配置类上,用来影响这些对象在集合注入或执行链中的先后顺序。
在 Spring 容器内部,负责比较顺序的核心类是 OrderComparator 和 AnnotationAwareOrderComparator。AnnotationAwareOrderComparator 会同时检查 @Order 注解和 Ordered 接口。对于被注入到 List 中的同类型 Bean,Spring 会按照排序结果重新组织集合顺序,这样业务代码直接遍历 List 就能拿到有序实例。
下面通过两个过滤器演示基础用法。假设系统中有两个过滤器,分别负责请求日志记录和鉴权校验。日志记录应该最先执行,鉴权过滤紧随其后,通过 @Order(1) 和 @Order(2) 可以控制。
@Component
@Order(1)
public class RequestLogFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("request log filter start");
chain.doFilter(request, response);
}
}
@Component
@Order(2)
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("auth filter start");
chain.doFilter(request, response);
}
}
上述代码中,数值更小的 @Order 对应更高优先级。当 Spring Boot 容器启动并装配这两个 Filter 时,日志过滤器会先于鉴权过滤器执行。如果去掉 @Order 注解,执行顺序可能取决于 Bean 的注册顺序或类名顺序,无法得到稳定保证。
二、@Order 与 Ordered 接口的优先级规则
@Order 注解和 Ordered 接口都用来表达优先级,但两者的作用方式略有不同。@Order 是声明式注解,适合标注在类或方法上;Ordered 接口需要实现 getOrder 方法,适合需要动态返回不同优先级值的场景。Ordered 接口提供了两个常量:HIGHEST_PRECEDENCE 对应 Integer.MIN_VALUE,表示最高优先级;LOWEST_PRECEDENCE 对应 Integer.MAX_VALUE,表示最低优先级。
当一个类同时标注 @Order 并实现 Ordered 接口时,Spring 排序器并不是简单叠加。AnnotationAwareOrderComparator 的查找顺序通常是先读取 @Order 注解,再读取 Ordered 接口。如果 @Order 存在,则优先采用 @Order 的值;否则如果实现了 Ordered 接口,则调用 getOrder 方法。实际项目中不建议同时使用,以免混淆优先级来源。
在 @Bean 方法上使用 @Order 也很常见。比如同一个接口有多个实现,在 @Configuration 类中通过 @Bean 声明,并在方法上标注不同 @Order。当这些 Bean 被 List 注入时,Spring 会根据 @Order 排序后注入。
@Configuration
public class HandlerConfig {
@Bean
@Order(100)
public Handler firstHandler() {
return new FirstHandler();
}
@Bean
@Order(10)
public Handler secondHandler() {
return new SecondHandler();
}
}
@Service
public class HandlerExecutor {
private final List<Handler> handlers;
public HandlerExecutor(List<Handler> handlers) {
this.handlers = handlers;
}
public void run() {
for (Handler handler : handlers) {
handler.handle();
}
}
}
在 HandlerExecutor 中注入的 List 会按照 @Order 排序,因此 secondHandler 对应的实例排在 firstHandler 之前。这种机制适合责任链模式或策略模式,避免手动对集合调用排序方法。
三、自动配置类顺序控制
Spring Boot 的自动配置也依赖顺序控制,但使用的注解和普通 Bean 不同。自动配置类可以通过 @AutoConfigureOrder、@AutoConfigureBefore 和 @AutoConfigureAfter 来调整装配顺序。@AutoConfigureOrder 类似于 @Order,但只对自动配置类生效。@AutoConfigureBefore 和 @AutoConfigureAfter 则直接指定目标类之间的相对顺序。
例如开发自定义 Starter 时,希望自己的配置类在 DataSource 自动配置之前加载,可以这样写:
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
public class CustomDataSourceWrapperAutoConfiguration {
@Bean
public DataSourceWrapper dataSourceWrapper() {
return new DataSourceWrapper();
}
}
这里使用 @AutoConfigureBefore 确保自定义配置类在 DataSourceAutoConfiguration 之前处理。@AutoConfigureAfter 则相反,指定当前配置类在某个目标配置类之后加载。自动配置排序常用于多 Starter 共存的环境,比如需要提前注册 BeanPostProcessor、提前加载配置属性等。
需要注意的是,@AutoConfigureOrder 只影响自动配置类之间的顺序,不会影响普通 @Configuration 类的加载。如果希望普通配置类也排序,可以在配置类上使用 @Order,但 @Order 对 @Configuration 类的生效范围有限,主要影响集合注入,而不一定改变 Bean 的创建顺序。
四、顺序控制失效的常见场景
很多项目在过滤器或拦截器上加了 @Order 却仍然没有按预期执行,原因往往在于注册方式不一致。如果是通过 FilterRegistrationBean 手动注册过滤器,不要只在 Filter 类上标注 @Order,而应该在 FilterRegistrationBean 上设置 order 属性。Spring Boot 对 FilterRegistrationBean 的排序会优先于 Filter 类上的 @Order。
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistration() {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new MyFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1);
return registration;
}
另一个容易踩坑的地方是 @Order 对 @Configuration 类中 @Bean 方法的控制。@Order 标注在 @Bean 方法上可以影响 List 注入顺序,但并不能保证这些 @Bean 方法被调用的先后顺序和 @Order 完全一致。Spring 调用 @Bean 方法创建实例时,还会受依赖关系、@DependsOn 以及配置类解析顺序影响。
拦截器的顺序控制稍有不同。如果使用 WebMvcConfigurer 注册拦截器,可以在 InterceptorRegistration 上使用 order 方法,而不是仅依赖 @Order 注解。对于多个拦截器,拦截器注册顺序和 order 值共同决定执行顺序。
五、实践建议与调试思路
在实际项目中,建议优先明确排序的目标是执行顺序还是集合注入顺序。如果是多个过滤器、拦截器的执行顺序,通常使用对应的注册器 API 设置 order;如果是同一接口多个实现需要在 List 中排序,使用 @Order 或 Ordered 接口最直接。对于自动配置类,始终保持使用 @AutoConfigureBefore、@AutoConfigureAfter 表达相对顺序,避免依赖隐式加载顺序。
调试顺序问题时,可以通过启动日志、Bean 初始化埋点或者打印 List 中的 Bean 名称来确认排序结果。如果发现顺序异常,先检查是否混用了不同的排序方式,比如类上 @Order 和注册器 order 并存,筛选出真正生效的优先级来源。
最后需要强调,顺序控制不能替代依赖关系。若一个 Bean 必须先于另一个 Bean 创建,最可靠的方式是在构造器或属性注入中建立依赖,或者使用 @DependsOn 声明依赖关系,而不是只依赖 @Order。排序解决的是同一批组件的执行或集合顺序,而依赖关系解决的是创建先后问题,两者需要配合使用。
Spring BootOrder注解Bean排序修改时间:2026-08-26 20:58:03