使用CommandLineRunner和ApplicationRunner接口及其源码分析
一 、使用实例
1.1 CommandLineRunner接口
使用CommandLineRunner接口类似于Main方法启动,可以接受一个字符串数组的命令行参数,以下为具体实现:
@Component public class MyCommandLineRunner implements CommandLineRunner{ @Override public void run(String... args) throws Exception{ //假装有代码 } }
1.2 ApplicationRunner 接口
此种方式与实现CommandLineRunner接口的区别就是他的参数是ApplicationArguments。
@Order(value = 1) @Component public class MyApplicationRunner implements ApplicationRunner{ @Override public void run(ApplicationArguments args) throws Exception{ //假装有代码 } }
二、源码分析
2.1 主程序启动
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
2.2 ConfigurableApplicationContext run(String... args)方法
调用以下方法,完成容器的初始化和其他必要的操作之后,执行callRunners(context, applicationArguments)方法。
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }
2.3 callRunners方法
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());
// 根据优先级进行排序,其中ApplicationRuner.class和CommandLineRunner.class混合在一起进行排序。 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); } } }