前戏
启动类
public static void main(String[] args) {
SpringApplication.run(IvernApplication.class, args);
}
调用SpringBootApplication的run方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
调用SpringBootApplication的initialize方法
public SpringApplication(Object... sources) {
initialize(sources);
}
initialize具体做了哪些事情?
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
// 判断是否是web环境,主要是通过判断能不找到Servlet和ConfigurableWebApplicationContext
this.webEnvironment = deduceWebEnvironment();
// 从spring.factories中获取ApplicationContextInitializer实例
setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 从spring.factories中获取ApplicationListener实例
setListeners(getSpringFactoriesInstances(ApplicationListener.class));
// 通过抛出异常并分析异常堆栈的方式获取程序入口类
this.mainApplicationClass = deduceMainApplicationClass();
}
重头戏SpringApplication.run()
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
// 开启StopWatch
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
// 从spring.factories获取SpringApplicationRunListener实例
SpringApplicationRunListeners listeners = getRunListeners(args);
// 调用所有的SpringApplicationRunListener的starting方法,实际上是只有一个EventPublishingRunListener
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments( args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 输出鬼画符
Banner printedBanner = printBanner(environment);
// 根据环境创建容器
context = createApplicationContext();
// 创建失败分析器
analyzers = new FailureAnalyzers(context);
// 容器准备
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 容器刷新
refreshContext(context);
// 容器刷新后置处理
afterRefresh(context, applicationArguments);
// 调用所有的SpringApplicationRunListener的finished方法,实际上是只有一个EventPublishingRunListener
listeners.finished(context, null);
// 结束StopWatch
stopWatch.stop();
// 输出容器启动过程相关数据,如耗时等
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch);
}
return context;
} catch (Throwable ex) {
// 异常处理
handleRunFailure(context, listeners, analyzers, ex);
// 重新抛出异常
throw new IllegalStateException(ex);
}
}