java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Springboot ApplicationRunner使用

Springboot ApplicationRunner的使用解读

作者:澄风

这篇文章主要介绍了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 提供了两种解决方案:

基本原理

项目在启动时会遍历所有的 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接口,来设定各个实现类的执行顺序。

选项参数与非选项参数

总结

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

您可能感兴趣的文章:
阅读全文