@Order注解,你理解错了!

开发 前端
当我们在注入一个集合类型时(有多个相同类型,如一个接口多个实现),我们可以通过@Order注解来控制它们在集合中的顺序。

环境:SpringBoot3.2.5

1. 简介

@Order注解是Spring框架中用于定义Bean执行顺序的优先级的一个注解,它位于spring-core包下。这个注解可以应用在类、方法和字段上,其作用是影响Bean注入到集合中的顺序,但不影响Bean的加载和实例化顺序。@Order 注解接受一个整数值作为参数,数值越小表示优先级越高。需要注意的是,@Order 注解或Ordered接口不能决定Bean的加载顺序。

注意:不会影响实例化的顺序,实例化的顺序是由你注册(通过扫描时,先发现的A,那就先实例化A)。

那 @Order 注解到底能用在哪些地方呢?接下来,我们将介绍一些常用场景下使用 @Order 注解的有效方法。

2. 实战案例

2.1 注入类型为集合

当我们在注入一个集合类型时(有多个相同类型,如一个接口多个实现),我们可以通过@Order注解来控制它们在集合中的顺序。

// 定义接口
public interface DAO {
  public void save() ;
}
// 下面3个实现类
@Component
public class A implements DAO {
  public void save() {
    System.out.println("A...") ;
  }
}
@Component
public class B implements DAO {
  public void save() {
    System.out.println("B...") ;
  }
}
@Component
public class C implements DAO {
  public void save() {
    System.out.println("C...") ;
  }
}
// 集合注入
@Resource
private List<DAO> daos ;
public void print() {
  for (DAO dao : daos) {
    dao.save() ; 
  }
}

运行上面程序,执行结果如下:

A...
B...
C...

分别添加@Order注解

@Order(2)
public class A...
@Order(1)
public class B...
@Order(0)
public class C...

再次运行

C...
B...
A...

这里的集合还可以是Array类型。都支持排序。

除了使用@Order注解,你还可以实现Ordered接口。同时,bean的注册方式也可以是通过配置类@Bean也可以添加@Order注解。

2.2 事件监听ApplicationListener

@Component
@Order(-1)
public class ListenerA implements ApplicationListener<PackEvent> {


  @Override
  public void onApplicationEvent(PackEvent event) {
    System.out.println("A Listener...") ;
  }
}
@Component
@Order(-2)
public class ListenerB implements ApplicationListener<PackEvent> {


  @Override
  public void onApplicationEvent(PackEvent event) {
    System.out.println("B Listener...") ;
  }
}

当发布PackEvent事件后,打印顺序如下:

B Listener...
A Listener...

同样你可以实现Ordered接口。

2.3 Application/CommandLineRunner

*Runner接口会在整个Spring Boot启动完成最后一个阶段(Spring容器已经完成加载),如下

图片图片

图片图片

@Component
@Order(0)
public class RunnerA implements CommandLineRunner {
  public void run(String... args) throws Exception {
    System.out.println("A Runner...") ;
  }
}
@Component
@Order(-1)
public class RunnerB implements CommandLineRunner {
  public void run(String... args) throws Exception {
    System.out.println("B Runner...") ;
  }
}

输出结果

B Runner...
A Runner...

一样通过配置类注册或者是实现Ordered接口都可以。

2.4 BeanPostProcessor

这是个Bean处理器(实例化Bean对象前后执行回调),我们只能通过实现Ordered接口来控制顺序。

public class APostProcessor implements BeanPostProcessor, Ordered {
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("A BeanPostProcessor") ;
    return bean ;
  }
  public int getOrder() {
    return -1 ;
  }
}
public class BPostProcessor implements BeanPostProcessor, Ordered {
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("B BeanPostProcessor") ;
    return bean ;
  }
  public int getOrder() {
    return -2 ;
  }
}

执行输出结果

B BeanPostProcessor
A BeanPostProcessor

目前不支持基于 @Order 注解方式。

除了实现Ordered接口外,你还可以实现PriorityOrdered接口。

2.5 BeanFactoryPostProcessor

该接口与上面的BeanPostProcessor基本一致,你只能通过实现Ordered接口的方式控制顺序。

2.6 @Aspect切面

@Aspect
@Order(-1)
public static class AspectA {
  @Pointcut("execution(* *(..))")
  private void a() {}
  @Before("a()")
  public void before() {
    System.out.println("A before...") ;
  }
}
@Aspect
@Order(-2)
public static class AspectB {
  @Pointcut("execution(* *(..))")
  private void b() {}
  @Before("b()")
  public void before() {
    System.out.println("B before...") ;
  }
}

切面执行

B before...
A before...
Demo save...

切面除了使用@Order还可以实现Ordered接口。

以上列出了我们工作中比较常用的一些场景使用上可以应用@Order注解或实现Ordered接口。而在Spring Boot环境下还有很多其它的一些情况都是支持排序的。

2.7 其它

FailureAnalyzer、ApplicationContextInitializer、ErrorPageRegistrar、ErrorViewResolver等。

其实如果是通过如下方式获取的,都是支持排序的

// 只要是通过该方式获取对象的,都是支持排序的
SpringFactoriesLoader#load(Class type)
责任编辑:武晓燕 来源: Spring全家桶实战案例源码
相关推荐

2021-08-12 10:36:18

order byMySQL数据库

2021-06-15 07:15:15

Oracle底层explain

2024-04-12 12:36:06

JSJavaScrip方式

2011-07-19 09:38:41

一维数组Junit静态成员

2021-08-11 15:13:54

数字化

2016-04-01 10:08:33

youtubeappuber

2022-12-06 08:37:43

2023-04-05 14:36:23

TortoisePython

2024-05-07 13:29:00

CSS选择器权重

2022-04-26 06:43:12

文档TCPLinux

2024-03-15 08:23:26

异步编程函数

2018-08-22 06:56:55

物联网商业模式IOT

2021-11-12 05:33:45

WiFi辐射无线路由器

2016-09-23 15:10:10

HTTPGETPOST

2019-05-15 16:15:08

HTTPGETPOST

2023-06-14 07:23:57

打印文档打印机

2019-08-08 16:00:08

HTTPGETPOST

2019-12-26 09:15:44

网络IOLinux

2021-04-23 07:27:31

内存分配CPU

2022-06-30 09:10:33

NoSQLHBaseRedis
点赞
收藏

51CTO技术栈公众号