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

2022年12月7日08:58:48

前言

  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方法进行排序,值越小优先级越高。

    • 作者:ZKC_开成
    • 原文链接:https://blog.csdn.net/zkc7441976/article/details/112548075
      更新时间:2022年12月7日08:58:48 ,共 3995 字。