1. 概述

本文将深入讲解 Spring 框架中的 @Order 注解。✅ 它的核心作用是定义被注解组件或 Bean 的排序优先级

该注解有一个可选的 value 参数,用于指定顺序值,默认值为 Ordered.LOWEST_PRECEDENCE,表示该组件在所有有序组件中优先级最低。
相对地,Ordered.HIGHEST_PRECEDENCE 则代表最高优先级,常用于需要优先执行的场景。

⚠️ 注意:这里的“顺序”不等于“加载顺序”或“初始化顺序”,它主要影响的是集合注入时 Bean 的排列顺序,这点后面会重点说明。


2. 何时使用 @Order

在 Spring 4.0 之前,@Order 主要用于控制 AspectJ 切面的执行顺序 —— 数值越小,切面越早执行。

✅ 从 Spring 4.0 开始,@Order 被扩展支持到集合类型的依赖注入场景。也就是说,当你通过 List<SomeService> 自动注入多个同类型 Bean 时,Spring 会根据 @Order 的值对它们进行排序。

举个实际场景:

  • 多个实现类实现同一个接口
  • 通过 List<Filter> 注入一组过滤器
  • 需要按特定顺序执行这些组件

这时候 @Order 就非常有用。否则 Spring 默认的注入顺序是不确定的(取决于类路径扫描顺序),容易踩坑 ❌。


3. 如何使用 @Order

我们通过一个简单例子来演示其用法。

3.1. 定义接口

首先定义一个 Rating 接口,用于表示商品评分等级:

public interface Rating {
    int getRating();
}

3.2. 创建带顺序的组件

接下来创建三个实现类,并通过 @Order 指定它们的优先级:

@Component
@Order(1)
public class Excellent implements Rating {

    @Override
    public int getRating() {
        return 1;
    }
}

@Component
@Order(2)
public class Good implements Rating {

    @Override
    public int getRating() {
        return 2;
    }
}

@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class Average implements Rating {

    @Override
    public int getRating() {
        return 3;
    }
}

📌 关键点:

  • Excellent 的 order 值为 1,优先级最高
  • Good 为 2,次之
  • Average 使用 LOWEST_PRECEDENCE,排在最后

⚠️ 注意:@Order 的值越小,优先级越高(排序越靠前)。


4. 测试验证

现在我们编写单元测试,验证注入后的列表是否按预期顺序排列:

public class RatingRetrieverUnitTest { 
    
    @Autowired
    private List<Rating> ratings;
    
    @Test
    public void givenOrder_whenInjected_thenByOrderValue() {
        assertThat(ratings.get(0).getRating(), is(equalTo(1))); // Excellent
        assertThat(ratings.get(1).getRating(), is(equalTo(2))); // Good
        assertThat(ratings.get(2).getRating(), is(equalTo(3))); // Average
    }
}

✅ 测试通过说明:Spring 确实按照 @Order 的值对 List<Rating> 中的 Bean 进行了排序。

💡 小贴士:这种机制在实现责任链模式、拦截器链、过滤器链时特别实用。


5. 总结与注意事项

我们已经掌握了 @Order 的基本用法和典型场景。再强调几个关键点:

适用场景

  • 注入 List<XXX>Set<XXX> 类型的 Bean 集合
  • 控制切面(Aspect)执行顺序
  • 自定义组件链式处理流程(如校验链、处理器链)

不适用场景

  • 控制 Bean 的初始化顺序 ❌
    Bean 的启动顺序由依赖关系(@DependsOn)决定,而不是 @Order。别搞混了!

📌 常见误区:

“我加了 @Order(1),这个 Bean 就会最先初始化?”
❌ 错!@Order 不影响单例 Bean 的创建顺序,只影响集合注入时的排序。

所有示例代码均可在 GitHub 获取:https://github.com/eugenp/tutorials/tree/master/spring-di-3


原始标题:@Order in Spring