Spring Boot中的ApplicationRunner和CommandLineRunner

Spring BootJava大约 3346 字

介绍

ApplicationRunnerCommandLineRunner两个runner都是在Spring Boot程序初始化完成后调用,可以做一些业务的初始化等。

一次性脚本也可以直接写在在runner中。

异同

ApplicationRunnerCommandLineRunner都可以命令行参数。

java -jar xxx.jar arg1 --foo=value1,value2 arg2

同步线程执行完成后再执行下一个runner,等所有线程(包括子线程)执行完毕后才退出程序。

ApplicationRunner将参数封装为操作参数与非操作参数。--foo为操作参数,arg1为非操作参数。

@Order(1)
@Component
public class TestApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //ApplicationRunner running, args#[arg1, arg2, --foo=value,value2]
        System.out.println("ApplicationRunner running, args#" + Arrays.asList(args.getSourceArgs()));
        List<String> nonOptionArgs = args.getNonOptionArgs();
        //non option args#[arg1, arg2]
        System.out.println("non option args#" + nonOptionArgs);
        List<String> foo = args.getOptionValues("foo");
        //option args#[value,value2]
        System.out.println("option args#" + foo);
        List<String> foo2 = args.getOptionValues("foo2");
        //not exist option args#null
        System.out.println("not exist option args#" + foo2);
        Thread.sleep(5000);
        new Thread(() -> {
            try {
                Thread.sleep(5000);
                System.out.println("ApplicationRunner sub thread, threadId#" + Thread.currentThread().getId());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

CommandLineRunner统一将参数读取为一个字符串,需自己解析。

@Order(2)
@Component
public class TestCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        //CommandLineRunner running, args#[arg1, arg2, --foo=value,value2], threadId#1
        System.out.println("CommandLineRunner running, args#" + Arrays.asList(args) + ", threadId#" + Thread.currentThread().getId());

        new Thread(() -> {
            try {
                Thread.sleep(5000);
                //CommandLineRunner sub thread, threadId#30
                System.out.println("CommandLineRunner sub thread, threadId#" + Thread.currentThread().getId());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

源码

SpringApplication.run中的callRunners@Order升序依次遍历运行。

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList<>();
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    AnnotationAwareOrderComparator.sort(runners);
    for (Object runner : new LinkedHashSet<>(runners)) {
        if (runner instanceof ApplicationRunner) {
            callRunner((ApplicationRunner) runner, args);
        }
        if (runner instanceof CommandLineRunner) {
            callRunner((CommandLineRunner) runner, args);
        }
    }
}

private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
    try {
        (runner).run(args);
    }
    catch (Exception ex) {
        throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
    }
}

代码

https://github.com/fendoudebb/learning/tree/master/java/learn-spring-boot/applicationrunner-commandlinerunner

阅读 331 · 发布于 2020-04-07

————        END        ————

扫描下方二维码关注公众号和小程序↓↓↓

昵称:
随便看看换一批