L
A D I N G

深入理解Spring的@Order注解和Ordered接口

前言

  Spring的@Order注解或者Ordered接口大家都知道是控制顺序的,那么它们到底是控制什么顺序的?是控制Bean的注入顺序,还是Bean的实例化顺序,还是Bean的执行顺序呢?那么我们先直接给出结论再来验证结论。
结论:Spring的@Order注解或者Ordered接口,不决定Bean的加载顺序和实例化顺序,只决定Bean的执行顺序。

实例论证:@Order不决定Bean的加载和实例化顺序

步骤一:创建DemoService接口和三个实现类,分别打上注解@Order(0)-DemoServiceImpl01、@Order(1)-DemoServiceImpl02、@Order(2)-DemoServiceImpl03,观察实例化顺序。

@Service @Order(0) public class DemoServiceImpl01 implements DemoService {      public DemoServiceImpl01() {         System.out.println("DemoServiceImpl01被实例化了");     } }  @Service @Order(1) public class DemoServiceImpl02 implements DemoService {      public DemoServiceImpl02() {         System.out.println("DemoServiceImpl02被实例化了");     }  }  @Service @Order(2) public class DemoServiceImpl03 implements DemoService {      public DemoServiceImpl03() {         System.out.println("DemoServiceImpl03被实例化了");     }  }  // 运行结果如下 DemoServiceImpl01被实例化了 DemoServiceImpl02被实例化了 DemoServiceImpl03被实例化了

步骤二:改变DemoService接口三个实现类的注解序值,@Order(2)-DemoServiceImpl01、@Order(1)-DemoServiceImpl02、@Order(0)-DemoServiceImpl03,观察实例化顺序

@Service @Order(2) public class DemoServiceImpl01 implements DemoService {      public DemoServiceImpl01() {         System.out.println("DemoServiceImpl01被实例化了");     } }  @Service @Order(1) public class DemoServiceImpl02 implements DemoService {      public DemoServiceImpl02() {         System.out.println("DemoServiceImpl02被实例化了");     }  }  @Service @Order(0) public class DemoServiceImpl03 implements DemoService {      public DemoServiceImpl03() {         System.out.println("DemoServiceImpl03被实例化了");     }  }  // 运行结果如下 DemoServiceImpl01被实例化了 DemoServiceImpl02被实例化了 DemoServiceImpl03被实例化了

结果:当改变DemoService接口的三个实现类注解序值时,类的加载和实例化顺序根本没有变化,即@Order注解不决定Bean的加载和实例化顺序。

实例论证:@Order决定Bean的执行顺序

步骤一:创建RunServiceImpl类,并通过构造函数依赖注入DemoService的三个实现类,且循序依次执行三个实现类方法,观察Bean的执行顺序。

@Service public class RunServiceImpl implements RunService {      public RunServiceImpl(List<DemoService> demoServices) {         demoServices.forEach(demoService -> demoService.say());     }  }  @Service @Order(0) public class DemoServiceImpl01 implements DemoService {      public DemoServiceImpl01() {         System.out.println("DemoServiceImpl01被实例化了");     }      @Override     public void say() {         System.out.println("DemoServiceImpl01被执行了");     } }  @Service @Order(1) public class DemoServiceImpl02 implements DemoService {      public DemoServiceImpl02() {         System.out.println("DemoServiceImpl02被实例化了");     }      @Override     public void say() {         System.out.println("DemoServiceImpl02被执行了");     }  }  @Service @Order(2) public class DemoServiceImpl03 implements DemoService {      public DemoServiceImpl03() {         System.out.println("DemoServiceImpl03被实例化了");     }      @Override     public void say() {         System.out.println("DemoServiceImpl03被执行了");     }  }  // 运行结果如下 DemoServiceImpl01被执行了 DemoServiceImpl02被执行了 DemoServiceImpl03被执行了

步骤二:改变DemoService接口三个实现类的注解序值,@Order(2)-DemoServiceImpl01、@Order(1)-DemoServiceImpl02、@Order(0)-DemoServiceImpl03,观察Bean的执行顺序。

@Service public class RunServiceImpl implements RunService {      public RunServiceImpl(List<DemoService> demoServices) {         demoServices.forEach(demoService -> demoService.say());     }  }  @Service @Order(2) public class DemoServiceImpl01 implements DemoService {      public DemoServiceImpl01() {         System.out.println("DemoServiceImpl01被实例化了");     }      @Override     public void say() {         System.out.println("DemoServiceImpl01被执行了");     } }  @Service @Order(1) public class DemoServiceImpl02 implements DemoService {      public DemoServiceImpl02() {         System.out.println("DemoServiceImpl02被实例化了");     }      @Override     public void say() {         System.out.println("DemoServiceImpl02被执行了");     }  }  @Service @Order(0) public class DemoServiceImpl03 implements DemoService {      public DemoServiceImpl03() {         System.out.println("DemoServiceImpl03被实例化了");     }      @Override     public void say() {         System.out.println("DemoServiceImpl03被执行了");     }  }  // 运行结果如下 DemoServiceImpl03被执行了 DemoServiceImpl02被执行了 DemoServiceImpl01被执行了

结果:当改变DemoService接口的三个实现类注解序值时,类的执行顺序也随之发生变化,即@Order决定Bean的执行顺序。

@Order注解或Ordered接口决定Bean的执行顺序原理分析

通过上面实例论证,大家应该清楚@Order注解或Ordered接口只是决定了Bean的执行顺序,那么Spring是如何在依赖注入时完成根据@Order注解或Ordered接口控制Bean执行顺序?
原理分析:
当通过构造函数或者方法参数注入进某个List<组件实现类>时,Spring的DefaultListableBeanFactory类会在注入时调用AnnotationAwareOrderComparator.sort(listA)帮我们去完成根据@Order或者Ordered接口序值排序。

备注:
AnnotationAwareOrderComparator是OrderComparator的子类,而OrderComparator实现比较器Comparator接口,AnnotationAwareOrderComparator.sort(listA)会调用父类sort方法,会根据@Order或者Ordered接口设置的int序值重写sort方法进行排序,值越小优先级越高。