文章目录

  • spring解决方案
  • 需求
  • 方案一可以通过SpringApplicationRunListener实现
  • 方案二(推荐)
  • 结果
  • 区别
  • idea设置参数
  • 源码解析执行时机


spring解决方案

需求

springboot项目启动完成执行指定方法

方案一可以通过SpringApplicationRunListener实现

方案二(推荐)

org.springframework.boot.ApplicationRunner
org.springframework.boot.CommandLineRunner
这两个接口是springBoot提供用来在spring容器加载完成后执行指定方法;
测试类:

@Slf4j
@Component
public class RunnerTest implements ApplicationRunner, CommandLineRunner {

  @Override
  public void run(ApplicationArguments args) throws Exception {
    System.out.println("服务启动RunnerTest   ApplicationRunner执行启动加载任务...");
    String[] sourceArgs = args.getSourceArgs();
    if (null != sourceArgs) {
      for (String s : sourceArgs) {
        System.out.println(s);
      }
    }
    System.out.println("服务启动RunnerTest   ApplicationRunner执行启动加载任务...option参数...");
    Set<String> optionNames = args.getOptionNames();
    for (String s : optionNames) {
      System.out.println(s + "" + JSONObject.toJSONString(args.getOptionValues(s)));
    }

  }

  @Override
  public void run(String... args) throws Exception {
    System.out.println("服务启动RunnerTest    CommandLineRunner 执行启动加载任务...");
    if (null != args) {
      for (String s : args) {
        System.out.println(s);
      }
    }
  }
}

执行结果:

springboot在启动完成后执行方法_ide

结果

通过执行结果可以看到,这两个接口都在springboot启动完成后执行的
ApplicationRunner接口的方法先执行,CommandLineRunner后执行;

区别

这两个方法的区别就是接口参数不同,CommandLineRunner传的就是main方法里面数组,而ApplicationRunner传的参数则进行了封装,ApplicationArguments封装成这个参数了.

idea设置参数

输入参数如下:
参数以空格分隔,–- 开头的参数会被解析成Option类型的参数;

test fsaf aaa vvv --mygroub=a,b --filePath=c:/aa --mygroub=cd

springboot在启动完成后执行方法_spring_02

springboot在启动完成后执行方法_spring_03

源码解析执行时机

首先看 SpringApplication.run()的方法:

springboot在启动完成后执行方法_spring_04

我们直接看执行Runners的地方:
就是重容器中获取ApplicationRunner,CommandLineRunner,然后遍历进行执行方法,CommandLineRunner执行也是从ApplicationArguments参数中获取args:

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);
		}
	}

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