先来一段代码:
public interface DefaultService {
void send();
}
@Component
@Order(2)
public class ServiceA implements DefaultService{
public ServiceA() {
System.out.println("constructor ServiceA");
}
@Override
public void send() {
System.out.println("ServiceA.send");
}
}
@Component
@Order(1)
public class ServiceB implements DefaultService{
public ServiceB() {
System.out.println("constructor ServiceB");
}
@Override
public void send() {
System.out.println("ServiceB.send");
}
}
@Component
public class SortedService {
@Autowired
private List<DefaultService> list;
@Autowired
private Map<String, DefaultService> map;
public void demo() {
Optional.of(list).ifPresent(l -> l.forEach(e -> System.out.println(e)));
//输出
//com.example.demo.service.ServiceB@19b843ba
//com.example.demo.service.ServiceA@2462cb01
//构造方法
//constructor ServiceA
//constructor ServiceB
}
}
我们可以看到,ServiceA和ServiceB的实例化顺序是不受@Order注解影响的,受影响的只是@Autowired自动注入时的一个注入的顺序(接口的实现类集合list是按照@Order顺序排列的)。
再来一段代码:
@Component
@Order(2)
public class RunnerA implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("RunnerA.run");
}
}
@Component
@Order(1)
public class RunnerB implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("RunnerB.run");
}
}
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
//RunnerB.run
//RunnerA.run
}
}
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
// 容器已经完成了初始化后,排序后调用接口实现类
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
其实在Spring官网已经对@Order注解的作用做了很详细的描述
Your target beans can implement the org.springframework.core.Ordered interface or use the @Order or standard @Priority annotation if you want items in the array or list to be sorted in a specific order. Otherwise, their order follows the registration order of the corresponding target bean definitions in the container.
You can declare the @Order annotation at the target class level and on @Bean methods, potentially for individual bean definitions (in case of multiple definitions that use the same bean class). @Order values may influence priorities at injection points, but be aware that they do not influence singleton startup order, which is an orthogonal concern determined by dependency relationships and @DependsOn declarations.
@Order值可能会影响注入点的优先级,但是要注意它们不会影响单例启动顺序,单例启动顺序是由依赖关系和@DependsOn声明决定的正交关系
Note that the standard javax.annotation.Priority annotation is not available at the @Bean level, since it cannot be declared on methods. Its semantics can be modeled through @Order values in combination with @Primary on a single bean for each type.