SpringBoot启动流程
概要
通常使用spring的模板创建的springboot启动类的main方法中只有一句话 SpringApplication.run(App.class, args);
。将其拆开后大致分为两个过程,new SpringApplication application = new SpringApplication(App.class);
和application.run(args);
下面分别说明new SpringApplication(App.class)
和application.run(args);
两个部分。
创建SpringApplication的过程(new SpringApplication(App.class))
整个过程分为如下几部分:
- 根据类路径推断web应用类型
- 加载BootstrapRegistryInitializer
- 加载ApplicationContextInitializer
- 加载ApplicationListener
- 根据栈帧信息推断主类
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 1. 根据类路径推断web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 2. 加载BootstrapRegistryInitializer
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// 3. 加载ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 4. 加载ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 5. 根据栈帧信息推断主类
this.mainApplicationClass = deduceMainApplicationClass();
}
1. 根据类路径推断web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
WebApplicationType中的静态方法deduceFromClasspath根据特定是否存在类名判断应用程序类型:
// servlet应用指示类
private static final String[] SERVLET_INDICATOR_CLASSES = {
"jakarta.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
// webmve指示类
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
// webflux指示类
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
// jersey指示类
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
static WebApplicationType deduceFromClasspath() {
// 若类路径包含WEBMVC_INDICATOR_CLASS,
// 且WEBMVC_INDICATOR_CLASS及JERSEY_INDICATOR_CLASS均不存在,
// 则此应用为REACTIVE类型应用
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
// 若SERVLET_INDICATOR_CLASSES中的某个类不存在
// 则此应用不是web应用
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils