资讯专栏INFORMATION COLUMN

CommandLineRunner与ApplicationRunner接口的使用及源码解析

tylin / 1196人阅读

摘要:实例定义一个实现,并纳入到容器中进行处理启动定义一个实现,并纳入到容器处理应用已经成功启动启动类测试,也可以直接在容器访问该值,配置参数,然后执行启动类打印结果接口发现二者的官方一样,区别在于接收的参数不一样。

引言

我们在使用SpringBoot搭建项目的时候,如果希望在项目启动完成之前,能够初始化一些操作,针对这种需求,可以考虑实现如下两个接口(任一个都可以)

org.springframework.boot.CommandLineRunner
org.springframework.boot.ApplicationRunner

CommandLineRunner、ApplicationRunner 接口是在容器启动成功后的最后一步回调(类似开机自启动)。

CommandLineRunner接口

官方doc: 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 @Order annotation.

接口被用作将其加入spring容器中时执行其run方法。多个CommandLineRunner可以被同时执行在同一个spring上下文中并且执行顺序是以order注解的参数顺序一致。

If you need access to ApplicationArguments instead of the raw String array consider using ApplicationRunner.

如果你需要访问ApplicationArguments去替换掉字符串数组,可以考虑使用ApplicationRunner类。

实例demo

定义一个ServerStartedReport实现CommandLineRunner,并纳入到srping容器中进行处理

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

@Order(2)
@Component
public class ServerStartedReport implements CommandLineRunner{
    @Override
    public void run(String... args) throws Exception {
        System.out.println("===========ServerStartedReport启动====="+ LocalDateTime.now());
    }
}

定义一个ServerSuccessReport实现CommandLineRunner,并纳入到spring容器处理

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Order(1)
@Component
public class ServerSuccessReport implements CommandLineRunner{
    @Override
    public void run(String... args) throws Exception {
        System.out.println("=====应用已经成功启动====="+ Arrays.asList(args));
    }
}

启动类测试,也可以直接在spring容器访问该值,

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        ApplicationArguments applicationArguments = context.getBean(ApplicationArguments.class);
        System.out.println("============");
        System.out.println("name="+applicationArguments.getOptionNames());
        System.out.println("values===="+applicationArguments.getOptionValues("developer.name"));
    }
}

配置参数,然后执行启动类

打印结果

ApplicationRunner接口

发现二者的官方javadoc一样,区别在于接收的参数不一样。CommandLineRunner的参数是最原始的参数,没有做任何处理。ApplicationRunner的参数是ApplicationArguments,是对原始参数做了进一步的封装。

ApplicationArguments是对参数(main方法)做了进一步的处理,可以解析--name=value的,我们就可以通过name来获取value(而CommandLineRunner只是获取--name=value)

可以接收--foo=bar这样的参数。

getOptionNames()方法可以得到foo这样的key的集合。

getOptionValues(String name)方法可以得到bar这样的集合的value。

实例demo

定义MyApplicationRunner类继承ApplicationRunner接口,

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Component
public class MyApplicationRunner implements ApplicationRunner{
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("===MyApplicationRunner==="+ Arrays.asList(args.getSourceArgs()));
        System.out.println("===getOptionNames========"+args.getOptionNames());
        System.out.println("===getOptionValues======="+args.getOptionValues("foo"));
        System.out.println("==getOptionValues========"+args.getOptionValues("developer.name"));
    }
}

启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

配置参数启动

打印结果

总结

用户使用CommandLineRunner或者ApplicationRunner接口均可实现应用启动初始化某些功能的需求,如果希望对参数有更多的操作,则可以选择实现ApplicationRunner接口。

扩展阅读 CommandLineRunner、ApplicationRunner执行流程源码分析

用户只要实现这两个接口,其中的run方法就会在项目启动时候被自动调用,那么究竟是在什么时候调用的呢?下面可以看一下Application的启动流程

SpringApplication.run(args)

this.afterRefresh(context, applicationArguments)方法

跟踪context.getBeansOfType()方法,具体实现在类DefaultListableBeanFactory中

总结:通过以上分析可知,实现这两个接口的类,在ApplicationContext.run()方法里被执行

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7401.html

相关文章

  • 如何在SpringBoot启动时执行初始化操作,两个简单接口就可以实现

    摘要:中有两个接口能实现该功能和。首先了解一下的基本用法,可以在系统启动后执行里面的方法执行数据初始化如果有多个类的话也可以通过注解指定每个类的执行顺序。 (一)概述 最...

    wuyangnju 评论0 收藏0
  • spring boot学习(4): 命令行启动

    摘要:在使用构建应用启动时,我们在工作中都是通过命令行来启动应用,有时候会需要一些特定的参数以在应用启动时,做一些初始化的操作。 在使用spring boot 构建应用启动时,我们在工作中都是通过命令行来启动应用,有时候会需要一些特定的参数以在应用启动时,做一些初始化的操作。 spring boot 提供了 CommandLineRunner 和 ApplicationRunner 这两个接...

    Binguner 评论0 收藏0
  • Spring Boot 2 - 使用CommandLineRunnerApplicationRun

    摘要:命令行参数传递之前我们说过使用的一大优势就是可以将工程直接打包成一个包而不需要单独部署。执行获取到参数执行结果我们可以发现,通过方法的参数可以很方便地获取到命令行参数的值。如果需要获取命令行参数时则建议使用。 本篇文章我们将探讨CommandLineRunner和ApplicationRunner的使用。 在阅读本篇文章之前,你可以新建一个工程,写一些关于本篇内容代码,这样会加深你对本...

    alogy 评论0 收藏0
  • Spring Boot启动退出加载项

    摘要:在一个初春的下午,甲跟我说,要在启动服务的时候,设置表自增的起始值。写完启动项,那么再把退出也说一下每一个都应该向注册一个钩子函数来确保能优雅地关闭。后面退出部分翻译地磕磕碰碰的,有不对的地方欢迎指正。原创不易,感谢支持。 在一个初春的下午,甲跟我说,要在Spring Boot启动服务的时候,设置表自增的起始值。于是我用屁股想了一下,不就是在main方法里折腾嘛。后来实际操作了一把,发...

    suosuopuo 评论0 收藏0
  • 最渣 Spring Boot 文章

    摘要:如删除临时文件,清除缓存信息,读取配置文件信息,数据库连接等。提供的接口也可以满足该业务场景。不同点中方法的参数为,而接口中方法的参数为数组。 spring-boot-starter-parent Maven的用户可以通过继承spring-boot-starter-parent项目来获得一些合理的默认配置。这个parent提供了以下特性: 默认使用Java 8 使用UTF-8编码 一...

    yanest 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<