深入理解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方法进行排序,值越小优先级越高。
我的专栏
本文地址:https://blog.csdn.net/zkc7441976/article/details/112548075
推荐阅读
-
深入理解Spring的@Order注解和Ordered接口
-
@Autowired 和 @Resource注解, 一个接口有多个实现类的时候Spring注入遇到的问题
-
深入理解Java的接口和抽象类
-
spring-mvc.xml 和 application-context.xml的配置与深入理解
-
深入理解spring之Aware接口的相关实现
-
关于Java Spring三级缓存和循环依赖的深入理解
-
@Autowired 和 @Resource注解, 一个接口有多个实现类的时候Spring注入遇到的问题
-
深入理解Java的接口和抽象类
-
深入理解Spring的@Order注解和Ordered接口
-
关于Java Spring三级缓存和循环依赖的深入理解