Springboot中的@Order如何使用

 更新时间:2022年02月08日 09:58:13   作者:湘西刺客王胡子  
本文主要介绍了Springboot中的@Order如何使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

在spring-boot 2.6.2下测试,@Order并不会影响bean的装载顺序,声明了@Component的类,无论是构造方法、@PostConstruct注解声明的方法,还是实现的InitializingBean接口中的afterPropertiesSet()方法,如果beanClass位于同样的目录层级,这些方法的调用只会受到className的顺序影响:

@Component
@Slf4j
@Order(2)
public class Bean1 implements InitializingBean {
    public Bean1() {
        log.info("construct bean1");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("initialled bean1");
    }

    @PostConstruct
    public void post() {
        log.info("post bean1");
    }
}

@Component
@Slf4j
@Order(1)
public class Bean2 implements InitializingBean {
    public Bean2() {
        log.info("construct bean2");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("initialled bean2");
    }

    @PostConstruct
    public void post() {
        log.info("post bean2");
    }
}

/* 结果打印顺序:
construct bean1
post bean1
initialled bean1
construct bean2
post bean2
initialled bean2
*/

观察@Order的注解说明,第一句写着: @Order defines the sort order for an annotated component. 提到这个注解只是对component排序,那么哪里会收到这个排序数值的影响呢?

这里先改造一下代码:

public interface IBean {
    void work();
}

@Component
@Slf4j
@Order(2)
public class Bean1 implements InitializingBean,CommandLineRunner,IBean {
    public Bean1() {
        log.info("construct bean1");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("initialled bean1");
    }

    @PostConstruct
    public void post() {
        log.info("post bean1");
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("running bean1");
    }

    @Override
    public void work() {
        log.info("bean1 is working");
    }
}

@Component
@Slf4j
@Order(1)
public class Bean2 implements InitializingBean, CommandLineRunner, IBean {
    public Bean2() {
        log.info("construct bean2");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("initialled bean2");
    }

    @PostConstruct
    public void post() {
        log.info("post bean2");
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("running bean2");
    }

    @Override
    public void work() {
        log.info("bean2 is working");
    }
}

@Service
@RequiredArgsConstructor
public class TestService {
    private final List<IBean> beans;

    public void test(){
        beans.forEach(IBean::work);
    }
}

启动之后执行TestService的test方法,得到如下顺序的日志:

construct bean1
post bean1
initialled bean1
construct bean2
post bean2
initialled bean2
running bean2
running bean1
bean2 is working
bean1 is working

作一下说明,@Order会影响依赖注入的顺序,如果存在同样类型的多个bean,且依赖声明使用了List<BeanInterface>,会将所有bean实例按照Order声明的顺序放入一个ArrayList中注入,如果用的是Collection或者Set则无效,因为类型本身无序。

而CommandLineRunner声明的run方法,会在bean被IOC容器装配完成之后被调用,方法注释简单明了的一句Callback used to run the bean可以理解为bean实例真正构建完成之后的回调方法,而这个方法会受到@Order的顺序影响,效果前面日志中已经体现,这里贴一下类注释:

Interface used to indicate that a bean should run when it is contained within a SpringApplication. Multiple CommandLineRunner beans can be defined within the same application context and can be ordered using the Ordered interface or @Order annotation.

除了以上两种用法,@Aspect声明的切面类、继承了OncePerRequestFilter的过滤器等,它们的作用顺序也会受到Order的影响。

注意:如果@Order注解配置在了@Configuration修饰的配置类中的@Bean方法修饰的方法上时,指定顺序并不会生效

顺便提一下另外一个注解:@Priority,以上@Order能起作用的地方,换成@Priority一样会生效,但在一种情况下,它的作用和@Order大为不同:

同一个接口类型有多个不同的bean实现类时,注入依赖时使用集合声明不会报错,但声明为单体类型时,如果各个Bean类使用了@Order声明,就会报required a single bean, but x were found的错误,这时有两种方法可以解决问题,一是在其中一个Bean类加上@Primary的注解声明为首要类型,另外一个就是把Order改成Priority,优先级最高的那个bean会被当作primary来对待。

到此这篇关于Springboot中的@Order如何使用的文章就介绍到这了,更多相关Springboot @Order内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java超详细分析讲解哈希表

    Java超详细分析讲解哈希表

    哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方,说起来可能感觉有点复杂,我想我举个例子你就会明白了,最典型的的例子就是字典
    2022-06-06
  • Spring Boot 3.4.0 结合 Mybatis-plus 实现动态数据源的完整方案

    Spring Boot 3.4.0 结合 Mybatis-plus 实

    本文详细介绍了在 Spring Boot 3.4.0 项目中结合 Mybatis-plus 实现动态数据源切换的完整方案,通过自定义注解和AOP切面,我们可以优雅地实现方法级别的数据源切换,满足多数据源场景下的各种需求,感兴趣的朋友一起看看吧
    2025-04-04
  • 走进JDK之不可变类String

    走进JDK之不可变类String

    这篇文章主要给大家介绍了JDK之不可变类String的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用JDK具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-04-04
  • springboot整合mybatis的超详细过程(配置模式+注解模式)

    springboot整合mybatis的超详细过程(配置模式+注解模式)

    这篇文章主要介绍了springboot整合mybatis的详细过程(配置模式+注解模式),这里我使用的是配置模式+注解模式所以需要配置全局文件,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • SpringBoot2零基础到精通之映射与常用注解请求处理

    SpringBoot2零基础到精通之映射与常用注解请求处理

    SpringBoot是一种整合Spring技术栈的方式(或者说是框架),同时也是简化Spring的一种快速开发的脚手架,本篇让我们一起学习映射、常用注解和方法参数的小技巧
    2022-03-03
  • 详解Spring Boot中@PostConstruct的使用示例代码

    详解Spring Boot中@PostConstruct的使用示例代码

    在Java中,@PostConstruct是一个注解,通常用于标记一个方法,它表示该方法在类实例化之后(通过构造函数创建对象之后)立即执行,这篇文章主要介绍了详解Spring Boot中@PostConstruct的使用,需要的朋友可以参考下
    2023-09-09
  • Java使用Maven BOM统一管理版本号的实现

    Java使用Maven BOM统一管理版本号的实现

    这篇文章主要介绍了Java使用Maven BOM统一管理版本号的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Hibernate传入Java对象创建动态表并录入数据

    Hibernate传入Java对象创建动态表并录入数据

    这篇文章主要介绍了Hibernate传入Java对象创建动态表并录入数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 解读SpringBoot接收List<Bean>参数问题(POST请求方式)

    解读SpringBoot接收List<Bean>参数问题(POST请求方式)

    这篇文章主要介绍了解读SpringBoot接收List<Bean>参数问题(POST请求方式),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • CentOS安装jdk的三种方法

    CentOS安装jdk的三种方法

    这篇文章主要为大家详细介绍了CentOS安装jdk的三种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02

最新评论