SpringBoot启动流程
- 创建
SpringApplication
对象。 - 在构造函数中初始化
Initializer
(setInitializers) 和Listener
(setListeners)。 - 调用
run
方法。 - 开启定时器
StopWatch
,stopWatch.start()
, 监听器, 记录启动时间。 - 根据
SpringApplicationRunListeners
以及参数来初始化环境。 - 准备环境配置, 注意
ConfigFileApplicationListener
是用来加载properies
文件的。 - 打印
banner
.printBanner()
方法。 - 创建容器上下文
createApplicationContext
。 prepareContext
准备容器上下文, 执行之前的Initializer
初始化, 并load
主bean
。refreshContext
刷新容器上下文, 里面onRefresh
方法启动web server
。afterRefresh
执行初始化完成后要做的操作,目前是空的。- 关闭计时器.
stopWatch.stop()
。 listener
启动完成。- 打印启动时间。
WebApplicationType
web应用类型, NONE
, SERVLET
, REACTIVE
.
Servlet web, 传统的 MVC Web项目。
Reactive web, 响应式Web项目(WebFlux)。
spring.factories
文件中配置有需要初始化的bean对象
。
引入 springboot
包的过程, 本质就是往 class path
下面放入 spring.factories
这个文件里配置类的过程。这样启动过程中就会自主地把这些类加载进来。
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));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 初始化 Initialzer,本质是 List 容器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 初始化 Listener,本质是 List 容器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 获取 main 函数所调用的类
this.mainApplicationClass = deduceMainApplicationClass();
}
SpringApplication
的run
方法。
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
// 开启计时器
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 获取 listener 监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 启动中
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境配置 profile。通过 ConfigFileApplicationListener 来加载配置文件
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 忽略的 bean
configureIgnoreBeanInfo(environment);
// 打印 banner
Banner printedBanner = printBanner(environment);
// 创建容器的上下文对象
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 准备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文 AbstractApplicationContext -> refresh -> invokeBeanFactoryPostProcessors -> SharedMetadataReaderFactoryContextInitializer register()
// 从 env 中获取 spring 所需要的一些数据
// aware 的组装
// 这一步加载了bean容器并保存在 beanFactories 中, 也做了 webServer 的启动
refreshContext(context);
// 执行Conetext初始化之后要做的操作,目前是空的
afterRefresh(context, applicationArguments);
// 关闭计时器
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 通知listener启动完成
listeners.started(context);
// 启动初始化,可以通过实现 ApplicationRunner 和 CommandLineRunner 接口实现
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;
}
本质上是对 listener
的不同维护。
ConfigurationClassParser.doProcessConfigurationClass()
bean的解析, 可以看到一些注解就在这里进行解析的。
ServletWebServerApplicationContext
的 createWebServer 方法创建 web
容器。