SpringBoot 启动成功初始化数据

本章节将介绍通过实现 CommandLineRunner 和 ApplicationRunner 接口,实现 Spring Boot 启动成功初始化数据。

如果你有一些资源需要在 Spring Boot 启动成功后才去加载,如:预加载配置、加载定时任务、初始化工作等。这些可以通过 Spring Boot 给我们提供的CommandLineRunner 接口和 ApplicationRunner 接口实现。

CommandLineRunner 接口

CommandLineRunner接口是在容器启动成功后的最后一步回调(类似开机自启动)。接口的源码如下:

package org.springframework.boot;

@FunctionalInterface
public interface CommandLineRunner {
    void run(String... args) throws Exception;
}

该接口只定义了一个 run() 方法,且该方法仅仅接收一个字符串数组。如果我们需要在 Spring Boot 启动成功后做些什么,如:初始化数据,需要实现该接口,实现 run 方法。例如:

package com.huangx.springboot.service;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;

/**
 * SpringBoot启动完成后自动运行
 */
@Service
public class AfterServiceStartedOther implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("AfterServiceStartedOther");
        for(String arg : args) {
            System.out.println(arg);
        }
    }

}

在运行 Spring Boot 时,添加参数,如下图:

SpringBoot 启动成功初始化数据

程序运行结果如下:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.1.RELEASE)
……
2020-07-20 23:04:31.759  INFO 16772 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
……
AfterServiceStartedOther
name1
name2
name3

从上面实例可以知道,run 方法的参数实际是上就是我们运行程序传递的参数。

ApplicationRunner 接口

CommandLineRunner接口和ApplicationRunner 接口基本一样,区别在于两者接收的参数不一样。CommandLineRunner 的参数是最原始的参数,没有做任何处理;而ApplicationRunner的参数是ApplicationArguments,对原始参数做了进一步的封装。下面通过实例进行说明:

package com.huangx.springboot.service;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;

import java.util.Arrays;

/**
 * SpringBoot启动完成后自动运行
 */
@Service
public class AfterServiceStarted implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("AfterServiceStarted");
        for(String name : args.getOptionNames()) {
            System.out.println(name + "=" + args.getOptionValues(name));
        }
    }

}

假如我们在这里配置了一些启动参数 --env=dev --level=debug,如下图:

SpringBoot 启动成功初始化数据

然后运行程序,结果如下:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.1.RELEASE)
……
2020-07-20 23:14:16.307  INFO 21612 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
……
AfterServiceStarted
level=[debug]
env=[dev]

如果使用 CommandLineRunner 实现上面实例,则 CommandLineRunner 只获取 --env=dev --level=debug 字符串。而 ApplicationRunner 可以将 --env=dev --level=debug 解析为 Key-Value,使得我们可以直接通过 key 来获取 value。

注意:ApplicationRunner 解析的参数必须使用“--”开头(双横线),否则不会解析。

设置 CommandLineRunner 和 ApplicationRunner 接口启动顺序

CommandLineRunner 和 ApplicationRunner 接口的工作方式类似,如果有多个启动回调接口实现类,我们还可以通过添加 @Order 注解指定顺序。

例如,我们将上面的 AfterServiceStarted 设置为第一个启动,AfterServiceStartedOther 设置为第二个启动。如下:

AfterServiceStarted.java

package com.huangx.springboot.service;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import java.util.Arrays;

/**
 * SpringBoot启动完成后自动运行
 */
@Order(1)
@Service
public class AfterServiceStarted implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("AfterServiceStarted");
        for(String name : args.getOptionNames()) {
            System.out.println(name + "=" + args.getOptionValues(name));
        }
    }

}

AfterServiceStartedOther.java

package com.huangx.springboot.service;

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

/**
 * SpringBoot启动完成后自动运行
 */
@Order(2)
@Service
public class AfterServiceStartedOther implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("AfterServiceStartedOther");
        for(String arg : args) {
            System.out.println(arg);
        }
    }

}

运行结果如下:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.1.RELEASE)
 ……
 2020-07-20 23:23:58.084  INFO 19048 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
 ……
AfterServiceStarted
level=[debug]
env=[dev]
AfterServiceStartedOther
--env=dev
--level=debug
尺有所短;寸有所长。物有所不足;智有所不明。——屈原《卜居》
1 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号