这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战
前言
SpringBoot启动流程主要分为两步, 我们可以结合源码来看看整体的启动流程
- 初始化一个SpringApplication对象。
- 执行该对象的run方法。
SpringApplication初始化流程
SpringApplication的初始化流程,SpringApplication的构造方法.
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断是否是Web项目
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 找到入口类
this.mainApplicationClass = deduceMainApplicationClass();
}
初始化流程中最重要的就是通过SpringFactoriesLoader找到 spring.factories文件中配置的 ApplicationContextInitializer和 ApplicationListener两个接口的实现类名称,以便后期构造相应的实例。
Spring Boot启动流程
我们从SpringBoot的Run方法开始看。
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
// 1. 通过SpringFactoriesLoader查找并加载所有的 SpringApplicationRunListeners
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 2. 创建并配置当前应用将要使用的 Environment
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
this.configureIgnoreBeanInfo(environment);
// 3. SpringBoot应用在启动时会输出Spring的LOGO
Banner printedBanner = this.printBanner(environment);
// 4. 根据是否是web项目,来创建不同的ApplicationContext容器。
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 5. 初始化ApplicationContext
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 6. 刷新容器
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}