前面分析了SpringBoot启动时,创建SpringApplication实例的流程,接下里分析调用SpringApplication的run()方法的主要执行流程。
代码入口:
SpringApplication.run(String… args)方法
public ConfigurableApplicationContext run(String... args) {
//监控SpringApplication启动耗时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//Spring上下文
ConfigurableApplicationContext context = null;
//SpringBoot异常上报处理器
Collection exceptionReporters = new ArrayList<>();
//设置无头模式
configureHeadlessProperty();
//从spring.factories中获取SpringBoot启动过程中配置的相关事件的监听器集合
SpringApplicationRunListeners listeners = getRunListeners(args);
//触发SpringApplicationRunListener的starting()方法
listeners.starting();
try {
// Provides access to the arguments that were used to run a {@link SpringApplication}.
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//Spring上下文创建前,创建环境变量对象
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
//输出Banner信息
Banner printedBanner = printBanner(environment);
//创建Spring应用上下文
context = createApplicationContext();
//创建SpringBoot异常上报器
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//refresh上下文之前的准备,并触发SpringApplicationRunListener的contextPrepared()方法
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//refresh上下文
refreshContext(context);
//refresh上下文之后的处理
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//触发Spring容器启动完成事件
listeners.started(context);
//从SpringContext中获取ApplicationRunner,CommandLineRunner的实例并调用
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
//触发Spring容器运行事件
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
//至此,SpringBoot启动完成,返回Spring上下文
return context;
}
总体流程如上,后续会就相关重要细节分析下。本章留意下SpringApplicationRunListener接口的各个方法都是在SpringBoot启动流程中哪些地方被调用的。
public interface SpringApplicationRunListener {
/**
* Called immediately when the run method has first started. Can be used for very
* early initialization.
*/
void starting();
/**
* Called once the environment has been prepared, but before the
* {@link ApplicationContext} has been created.
* @param environment the environment
*/
void environmentPrepared(ConfigurableEnvironment environment);
/**
* Called once the {@link ApplicationContext} has been created and prepared, but
* before sources have been loaded.
* @param context the application context
*/
void contextPrepared(ConfigurableApplicationContext context);
/**
* Called once the application context has been loaded but before it has been
* refreshed.
* @param context the application context
*/
void contextLoaded(ConfigurableApplicationContext context);
/**
* The context has been refreshed and the application has started but
* {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
* ApplicationRunners} have not been called.
* @param context the application context.
* @since 2.0.0
*/
void started(ConfigurableApplicationContext context);
/**
* Called immediately before the run method finishes, when the application context has
* been refreshed and all {@link CommandLineRunner CommandLineRunners} and
* {@link ApplicationRunner ApplicationRunners} have been called.
* @param context the application context.
* @since 2.0.0
*/
void running(ConfigurableApplicationContext context);
/**
* Called when a failure occurs when running the application.
* @param context the application context or {@code null} if a failure occurred before
* the context was created
* @param exception the failure
* @since 2.0.0
*/
void failed(ConfigurableApplicationContext context, Throwable exception);
}
具体可以查看org.springframework.boot.SpringApplicationRunListeners的实现。
总结:
SpringApplication.run(String… args)方法的主要流程:
(1) 从spring.factories中获取SpringBoot启动过程中配置的相关事件的监听器集合;
(2) 创建ApplicationArguments实例,为SpringApplication运行提供参数获取;
注意:是main方法参数,不是环境变量。
(3) 创建Spring上下文环境变量ConfigurableEnvironment的实例;
(4) 控制台打印Spring的Banner信息;
(5) 创建Spring上下文实例,接口类型是ConfigurableApplicationContext,默认的实例是:
org.springframework.context.annotation.AnnotationConfigApplicationContext
(6) 从spring.factories中获取SpringBootExceptionReporter异常处理器集合;
(7) 刷新Spring上下文前的相关处理;
(8) 刷新Spring上下文;
(9) 打印SpringBoot启动完成的耗时等相关日志信息;
(10) 从Spring上下文中获取ApplicationRunner,CommandLineRunner的实例并调用;
(11) 返回ConfigurableApplicationContext对象,至此SpringBoot启动完成;
上述过程中,隐去了SpringBoot启动过程中,相关监听器SpringApplicationRunListener实例集合的调用,具体查看SpringApplicationRunListener类。
后续将着重分析SpringBoot启动过程中,对Spring上下文的处理。