Springboot ApplicationRunner的使用解读

 更新时间:2023年05月16日 09:38:30   作者:澄风  
这篇文章主要介绍了Springboot ApplicationRunner的使用解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Springboot ApplicationRunner使用

ApplicationRunner介绍

ApplicationRunner是在应用容器启动之后会回调到,在ApplicationStartedListener调用之后被调用。

如果说ApplicationListener中有阻塞,那么ApplicationRunner也都不会被调用。

@Component
public class ApplicationRunnerTest implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(args);
    }
}

我们可以在applicationRunner中做一些异步启动的操作,比如实例化Kafka客户端,异步加载缓存等等在服务启动之后不立马提供服务的操作。

通过分析源码可以知道runner实在容器加载完成以及ApplicationStartedListener调用之后进行回调的。

ApplicationRunner为什么不被调用

问题描述

在项目中写了一个ApplicationRunner 来启动消费队列线程,结果启动的时候applicationRunner的run方法死活不被调用。

问题分析

通过debug发现,在springboot初始化完环境refresh context之后就会调用started listener然后调用application runner,如果started listner 存在阻塞的话就会导致后续的application runner 不被运行。

而我在另一个组件中使用ApplicationListener<ApplicationStartedEvent> 去启动了netty server,启动netty server会导致当前线程阻塞以至于application runner 不被调用。

问题解决

在listener和Runner当中尽量启用线程来跑阻塞而不是直接去跑阻塞任务。

ApplicationRunner的作用是什么?

有时针对一些特殊的业务场景,需要在系统启动时执行某些任务,如:配置文件的加载、数据库的初始化等等操作。

SpringBoot 提供了两种解决方案:

  • 一种是使用CommandLineRunner
  • 另一种是使用 ApplicationRunner

基本原理

项目在启动时会遍历所有的 ApplicationRunner 的实现类并调用其中的 run 方法,如果在系统中有多个 ApplicationRunner的实现类,可以使用 @Order 注解对这些实现类的调用顺序进行排序(数字越小越先执行);run方法的参数是系统启动时传入的参数,即入口类中main方法的参数(在调用SpringApplication.run方法时传入到 SpringBoot项目的上下文环境中)。

如何使用

@Component
@Slf4j
@Order(1)
public class MyApplicationRunner implements ApplicationRunner {
    // ApplicationArguments, 需要区分选项参数和非选项参数;
    // 选项参数, 通过ApplicationArguments的getOptionNames()方法获取所有选项名称即参数的KEY, 然后通过 getOptionValues()方法根据参数KEY, 获取实际值(它会返回一个列表字符串), 一般为: --user-name=ROCKY --age=30
    // 非选项参数, 通过ApplicationArguments的getNonOptionArgs()方法获取一个参数值数组;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // TO DO SOMETHING...
    }
}

ApplicationRunner和CommandLineRunner的区别

@Component
@Slf4j
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        // TO DO SOMETHING...
    }
} 

ApplicationRunner与CommandLineRunner的主要区别体现在run方法的参数上,CommandLineRunner中的run方法的参数是参数数组;ApplicationRunner中的run方法的参数是ApplicationArguments对象。

执行顺序

系统支持创建多个CommandLineRunner或ApplicationRunner的实现类,可以使用@Order注解或实现Ordered接口,来设定各个实现类的执行顺序。

选项参数与非选项参数

  • 选项参数:可以理解为Spring Boot 提供的参数格式,以–开头,使用=分割键值对,如:java -jar XXX.jar --name=ROCKY --age=30 --spring.profiles.active=dev;
  • 非选项参数:不是以–开头,也没有设置值的单一参数KEY只有值,如:java -jar XXX.jar --name=ROCKY --age=30 --spring.profiles.active=dev 陕西 西安 雁塔区,其中"陕西 西安 雁塔区" 就是非选项参数;
  • 系统参数:-Dxxxx是设置JAVA运行上下文的参数语法,用于配置一些环境变量,如:java -jar XXX.jar -Dserver.port=8081 --name=ROCKY --age=30 --spring.profiles.active=dev 陕西 西安 雁塔区,其中"-Dserver.port"就是系统参数。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • springboot如何使用logback-spring配置日志格式,并分环境配置

    springboot如何使用logback-spring配置日志格式,并分环境配置

    这篇文章主要介绍了springboot如何使用logback-spring配置日志格式,并分环境配置的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 深入探讨Java多线程中的volatile变量

    深入探讨Java多线程中的volatile变量

    这篇文章主要为大家详细并深入的探讨Java多线程中的volatile变量,volatile用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • logback整合rabbitmq实现消息记录日志的配置

    logback整合rabbitmq实现消息记录日志的配置

    这篇文章主要介绍了logback整合rabbitmq实现消息记录日志的配置,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-12-12
  • 使用kafka-console-consumer.sh不停报WARN的问题及解决

    使用kafka-console-consumer.sh不停报WARN的问题及解决

    这篇文章主要介绍了使用kafka-console-consumer.sh不停报WARN的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 基于SSM框架之个人相册示例代码

    基于SSM框架之个人相册示例代码

    本篇文章主要介绍了基于SSM框架之个人相册示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • Java 高并发六:JDK并发包2详解

    Java 高并发六:JDK并发包2详解

    本文主要介绍Java高并发这里整理了详细资料,并讲解了 1. 线程池的基本使用 2. 扩展和增强线程池 3. ForkJoin的知识,有兴趣的小伙伴可以参考下
    2016-09-09
  • 关于SpringBoot创建存储令牌的媒介类和过滤器的问题

    关于SpringBoot创建存储令牌的媒介类和过滤器的问题

    这篇文章主要介绍了SpringBoot创建存储令牌的媒介类和过滤器的问题,需要在配置文件中,添加JWT需要的密匙,过期时间和缓存过期时间,具体实例代码参考下本文
    2021-09-09
  • Java Map集合详解与演示

    Java Map集合详解与演示

    Map用于保存具有映射关系的数据,Map集合里保存着两组值,一组用于保存Map的ley,另一组保存着Map的value,可以理解为Map中的元素是两个对象,一个对象作为键,一个对象作为值。键不可以重复,但是值可以重复
    2021-11-11
  • Java单例模式的深入了解

    Java单例模式的深入了解

    这篇文章主要为大家介绍了Java单例模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • Java dom4j创建解析xml文档过程解析

    Java dom4j创建解析xml文档过程解析

    这篇文章主要介绍了Java dom4j创建解析xml文档过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07

最新评论