Spring中@order注解用法实战教程

目录
  • 前言
  • 一、观察@order源码
  • 二、@order实战
  • 三、@order失效原因
  • 四、解决排序问题
  • 五、排序源码分析
  • 六、@AutoConfigureOrder
  • 总结

前言

@order注解是spring-core包下的一个注解,@Order的作用是定义Spring IOC容器中Bean的执行顺序的优先级(这里的顺序也可以理解为存放到容器中的先后顺序)。开发过程当中有时候经常会出现配置依赖关系,例如注入A对象使用了

@ConditionalOnBean(B.class),意思是要求容器当中必须存在B.class的实例的时候,才会进行注入A。这时候我们就必须保证B对象在注入A对象前进行注入。

一、观察@order源码

(1)源码当中有三个元注解:

  • @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}): 使用范围接口、类、枚举、注解、方法、字段
  • @Retention(RetentionPolicy.RUNTIME): @Retention是用来修饰注解的生命周期的,RetentionPolicy.RUNTIME代表的是不仅被保存到class文件中,jvm加载class文件之后,仍然存在;一直有效!
  • @Documented: @Documented和@Deprecated注解长得有点像,@Deprecated是用来标注某个类或者方法不建议再继续使用,@Documented只能用在注解上,如果一个注解@B,被@Documented标注,那么被@B修饰的类,生成Javadoc文档时,会显示@B。

(2)属性:

@order当中只要一个value属性,而且还是int类型,值越低优先级越高,默认值是Ordered.LOWEST_PRECEDENCE,表示最低优先级(输给任何其他指定的顺序值)。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
    int value() default 2147483647;
}

官网注释:https://github.com/spring-projects/spring-framework/blob/main/spring-core/src/main/java/org/springframework/core/annotation/Order.java

二、@order实战

(1)自定义两个配置类

我们要求Config2先进行加载,然后通过@order来排序测试一下

@Configuration
public class Config1 {

    public Config1() {
        System.out.println("Config1构建了");
    }
}

@Configuration
public class Config2 {

    public Config2() {
        System.out.println("Config2构建了");
    }
}

(2)启动项目测试:默认是先创建的Config1后创建的Config2

(3)既然order可以控制加载顺序,那我们来试验一下,然后让Config2 先加载

@Configuration
@Order(2)
public class Config1 {

    public Config1() {
        System.out.println("Config1构建了");
    }
}

@Configuration
@Order(1)
public class Config2 {

    public Config2() {
        System.out.println("Config2构建了");
    }
}

但是好像没什么卵用

(4)分析原因

目前这两个是在同包情况下不起作用。

于是进行分开了

分开之后竟然生效了

(5)但是分开也是将Config2放到了上面的包当中,于是我又改成了Config1放到最上面,这样进行测试,结果又失效了

(6)于是我又放在了同包下,将Config2命名为A开头的,这样他就放到了最上面,于是这样同样也生效了。

期间我还尝试着将@Configuration都改为使用@Component,结果仍然不变。

得出结论:@order指定加载顺序还跟类的命名和存放位置有关!假如有Config1Config2两个类在一个包下,要求是Config2先加载:

  • 这时候设置Config2@order值就算是小于Config1@order值同样也是Config1先加载。
  • 如果同包情况下可以重新命名Config2,只要在Config1上面就行。
  • 或者拆开不同包也可以,但是Config2所在的包也必须比Config1所呆的包上面。

这样才能保证@Order生效!

三、@order失效原因

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-constructor-injection

最关键的一句话:您可以在目标类级别和@Bean方法上声明@Order注释,可能针对的是单个bean定义(如果多个定义使用同一个bean类)。@Order值可能会影响注入点的优先级,但请注意,它们不会影响单例启动顺序,这是由依赖关系和@DependsOn声明确定的正交关注。

我理解的注入点的优先级应该是指的存放容器的先后顺序,也就是他并不会影响启动顺序。

四、解决排序问题

我们不可能每次遇到这种问题又是改名又是换包的,所以,springboot提供了如下三个注解可以控制顺序:

  • @AutoConfigureAfter:当前配置类在指定配置类之后执行
  • @AutoConfigureBefore:当前配置类在指定配置类之前执行
  • @AutoConfigureOrder:指定优先级,数值越小,优先级越高。

(1)首先将代码改回原来的样子

(2)在Config2使用@AutoConfigureBefore(Config1.class),代表的是在config1加载前进行加载

@Configuration
public class Config1 {

    public Config1() {
        System.out.println("Config1构建了");
    }
}

@Configuration
@AutoConfigureBefore(Config1.class)
public class Config2 {

    public Config2() {
        System.out.println("Config2构建了");
    }
}

(3)输出结果,显然还是没生效

可能有时候走了运给你一种错觉还真的配置成功了。实际上这种方式是不可行的,以上三个注解只有针对自动配置类才会生效。

在autoconfigure包下就有spring.factories,这个文件配置了自动配置类,springboot会读取这个文件的,我们也可以在自己项目上定义spring.factories,这样我们的配置类对于@AutoConfigureAfter注解就可以生效了。

(4)自定义spring.factories

第一行是固定的,后面的就是全类名,虽然只有Config2使用了注解,但是需求是和Config1进行排序,所以这两个都得加。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gzl.cn.springbootcache.config.Config2,\
com.gzl.cn.springbootcache.config.Config1

(5)测试,成功解决

五、排序源码分析

针对于@AutoConfigure那三个注解原理:其实关键的代码还是在AutoConfigurationImportSelector中,将自动配置类从spring.factories加载出来之后会根据条件排序(只有自动配置类!),在selectImports()方法中最后一行代码如下:

紧接着会走到这个地方,实际上是分了三步排序:

  • 先按照文件名字母排序
  • 按照@AutoConfigureOrder进行排序
  • 按照 @AutoConfigureBefore和@AutoConfigureAfter排序

从上面配置的顺序可以知道,最终决定权还是在@AutoConfigureAfter、@AutoConfigureBefore这两个注解。

当我们不设置spring.factories的时候,这里面压根都没有这两个类!

六、@AutoConfigureOrder

这种也是可以的!当然前提也是需要配置spring.factories

@Configuration
@AutoConfigureOrder(2)
public class Config1 {

    public Config1() {
        System.out.println("Config1构建了");
    }
}

@Configuration
@AutoConfigureOrder(1)
public class Config2 {

    public Config2() {
        System.out.println("Config2构建了");
    }
}

总结

到此这篇关于Spring中@order注解用法的文章就介绍到这了,更多相关Spring @order注解用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot Application核心注解详解

    目录 @SpringBootApplication @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan @SpringBootApplication @SpringBootApplication 是一个“三体”结构,实际上它是一个复合 Annotation: ​ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @In

  • Spring注解与P/C命名空间超详细解析

    目录 注解实现自动装配 @Autowire注解 @Qualifier注解 @Resource注解 @Component @Scope @ComponentScan @Bean @Configuration @Value P命名空间注入 C命名空间注入 Spring开发包名解释 Java方式配置 注解实现自动装配 @Autowire注解 @Autowire注解,自动装配通过类型,名字如果Autowire不能唯一自动装配上属性, 则需要通过@Qualifier(value=“xxx”) 配置: 导入

  • Spring框架基于注解的AOP之各种通知的使用与环绕通知实现详解

    目录 一.基于注解的AOP之各种通知的使用 二.基于注解的AOP之环绕通知 一.基于注解的AOP之各种通知的使用 1.在切面中,需要通过指定的注解将方法标识为通知方法 @Before:前置通知,在目标对象方法执行之前执行 @After:后置通知,在目标对象方法的finally子句中执行 @AfterReturning:返回通知,在目标对象方法返回值之后执行 @AfterThrowing:异常通知,在目标对象方法的catch子句中执行 声明重用写入点表达式 @Pointcut("execution

  • Spring @Conditional注解示例详细讲解

    目录 前言: 示例: 标注在方法上: 标注在类上: 多个条件类: 前言: @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean. @Conditional的定义: //此注解可以标注在类和方法上 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditi

  • Spring中Transactional注解使用的心得(推荐)

    事务特性 @Transactional注解是用于事务控制的,需要知道事务的ACID特征:即原子性(Atomicity,或称不可分割性).一致性(Consistency).隔离性(Isolation,又称独立性).持久性(Durability). 事务是用来控制数据的ACID特性的,用于保证数据的正确性和完整性. @Transactional注解有两种使用方式: (1)标注在类上面:当作用于类上时,该类的所有public方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别

  • Spring注解Autowired的底层实现原理详解

    目录 一.Autowired注解的用法 1.概述 2.应用 3.具体用法 二.Autowired自动装配的过程 一.Autowired注解的用法 1.概述 使用spring开发时,进行配置主要有两种方式,一是xml的方式,二是java config的方式. spring技术自身也在不断的发展和改变,从当前springboot的火热程度来看,java config的应用是越来越广泛了,在使用java config的过程当中,我们不可避免的会有各种各样的注解打交道,其中,我们使用最多的注解应该就是@

  • 浅析Spring基于注解的AOP

    目录 一.准备工作 二.基于注解的AOP之前置通知 三.基于注解的AOP之切入点表达式的语法和重用以及获取连接点的信息 ①切入点表达式的语法 ②获取连接点的信息 ③重用写入点表达式 一.准备工作 ①创建一个Maven工程 ②添加依赖 在IOC所需依赖基础上再加入下面依赖即可: <!-- spring-aspects会帮我们传递过来aspectjweaver --> <dependency> <groupId>org.springframework</groupId

  • 一文带你了解SpringBoot中常用注解的原理和使用

    目录 @AutoConfiguration @Import @ConfigurationProperties @AutoConfiguration 读取所有jar包下的 /META-INF/spring.factories 并追加到一个 LinkedMultiValueMap 中.每一个url中记录的文件路径如下: file:/C:/Users/wangchao/apache-maven-3.5.0/repo/com/baomidou/mybatis-plus-boot-starter/3.5.

  • Spring中@order注解用法实战教程

    目录 前言 一.观察@order源码 二.@order实战 三.@order失效原因 四.解决排序问题 五.排序源码分析 六.@AutoConfigureOrder 总结 前言 @order注解是spring-core包下的一个注解,@Order的作用是定义Spring IOC容器中Bean的执行顺序的优先级(这里的顺序也可以理解为存放到容器中的先后顺序).开发过程当中有时候经常会出现配置依赖关系,例如注入A对象使用了 @ConditionalOnBean(B.class),意思是要求容器当中必

  • spring的@Transactional注解用法解读

    概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framework对事务管理提供了一致的抽象,其特点如下: 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects) 支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用 提供比其他事务API如JTA更简单的编程式事务管

  • Spring中@Async注解实现异步调详解

    异步调用 在解释异步调用之前,我们先来看同步调用的定义:同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果. 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕,继续执行下面的流程.例如, 在某个调用中,需要顺序调用 A, B, C三个过程方法:如他们都是同步调用,则需要将他们都顺序执行完毕之后,过程才执行完毕: 如B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是执行开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了. 概述说明 Sp

  • Spring中异步注解@Async的使用、原理及使用时可能导致的问题及解决方法

    前言 其实最近都在研究事务相关的内容,之所以写这么一篇文章是因为前面写了一篇关于循环依赖的文章: <Spring循环依赖的解决办法,你真的懂了吗> 然后,很多同学碰到了下面这个问题,添加了Spring提供的一个异步注解@Async循环依赖无法被解决了,下面是一些读者的留言跟群里同学碰到的问题: 本着讲一个知识点就要讲明白.讲透彻的原则,我决定单独写一篇这样的文章对@Async这个注解做一下详细的介绍,这个注解带来的问题远远不止循环依赖这么简单,如果对它不够熟悉的话建议慎用. 文章要点 @Asy

  • Spring中@DependsOn注解的作用及实现原理解析

    本文给大家讲解Spring中@DependsOn注解的作用及实现原理! 官方文档解释 Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another thro

  • Spring中@Configuration注解修改的类生成代理原因解析

    目录 前言 说明 场景 处理分析 总结 前言 在Spring中只要被@Configuration注解修饰的类,Spring就会为其生成代理对象,至于这样做的主要原因就是为了解决生成对象的单例问题. 说明 实际上作者在ConfigurationClassEnhancer这个类也有注解说明 场景 如果Spring不做处理,下面输出的一定的是false,但是实际上输出的结果是true,那么只有可能是代理类做了特殊处理. @Configuration public class MyConfigurati

  • SpringMVC中@RequestMapping注解用法实例

    目录 1 修饰类和方法 2 value 3 method 4 params和headers 5 Ant路径 5 @PathVariable 6 HiddenHttpMethodFilter 7 @RequestParam 8 @RequestHeader 9 @CookieValue 总结 1 修饰类和方法 package site.exciter.springmvc.handlers; import org.springframework.stereotype.Controller; impo

  • 最新MySql8.27主从复制及SpringBoot项目中的读写分离实战教程

    目录 最新MySql8.27主从复制以及SpringBoot项目中的读写分离实战 1.MySql主从复制 2.配置-主库Master 3.配置-从库Slave 3.主从复制测试 4.读写分离案例 4.1.Sharding-JDBC框架介绍 最新MySql8.27主从复制以及SpringBoot项目中的读写分离实战 1.MySql主从复制 MySQL主从复制是一个异步的复制过程,底层是基于MySQL1数据库自带的二进制日志功能.就是一台或多台MySQL数据库(slave,即从库)从另一台ySQL数

  • 浅谈Spring 中 @EnableXXX 注解的套路

    目录 前言 设计目标 @EnableScheduling (导入一个 @Configuration 类) @EnableTransactionManagement(导入一个 ImportSelector) @EnableAspectJAutoProxy (在 Bean 定义层导入) 结论 前言 在 Spring 框架中有很多实用的功能,不需要写大量的配置代码,只需添加几个注解即可开启. 其中一个重要原因是那些 @EnableXXX 注解,它可以让你通过在配置类加上简单的注解来快速地开启诸如事务管

随机推荐