Spring Boot 启动时做了什么
Posted 恍若昨夕
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot 启动时做了什么相关的知识,希望对你有一定的参考价值。
注解
@SpringBootApplication注解 中包括三个注解:
- @EnableAutoConfiguration:借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器
- @Configuration:Spring Ioc容器的配置类,
- @ComponentScan:组件扫描,可自动发现和装配Bean,功能其实就是自动扫描并加载符合条件的组件或者bean定义,最终将这些bean定义加载到IoC容器中.默认扫描SpringApplication的run方法里的class所在的包路径下文件,所以最好将该启动类放到根包路径下
启动方法
创建SpringApplication实例
public SpringApplication(Class... primarySources) {
this((ResourceLoader)null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
// 初始化资源加载器
this.resourceLoader = resourceLoader;
// 断言主要资源类不为空
Assert.notNull(primarySources, "PrimarySources must not be null");
// 初始化主要加载资源类集合
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
// 判断项目类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 设置初始化器
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置监听器
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//推断程序主类
this.mainApplicationClass = this.deduceMainApplicationClass();
}
初始化主要加载资源类集合
判断项目类型
public enum WebApplicationType {
NONE,
SERVLET,
REACTIVE;
private static final String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
private WebApplicationType() {
}
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
return REACTIVE;
} else {
String[] var0 = SERVLET_INDICATOR_CLASSES;
int var1 = var0.length;
for(int var2 = 0; var2 < var1; ++var2) {
String className = var0[var2];
if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
return NONE;
}
}
return SERVLET;
}
}
}
根据classpath中是否包含指定类
1.REACTIVE:ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)
2.SERVLET:(!ClassUtils.isPresent("javax.servlet.Servlet", (ClassLoader)null)) && (!ClassUtils.isPresent("org.springframework.web.context.ConfigurableWebApplicationContext", (ClassLoader)null))
3.NONE
设置应用上线文初始化器 ApplicationContextInitializer
路径下META-INF/spring.factories文件ApplicationContextInitializer 接口的所有配置的类路径名称,用来初始化指定的 Spring 应用上下文,如注册属性资源、激活 Profiles 等。
- 获取类加载器
- 获取
ApplicationContextInitializer
实例名称 - 创建初始化器实例
- 给初始化器实例排序
设置监听器 ApplicationListener
路径下META-INF/spring.factories文件,使用初始化器相同的方法设置
设置程序的主类
执行run方法
以上是关于Spring Boot 启动时做了什么的主要内容,如果未能解决你的问题,请参考以下文章
1. SOFAJRaft源码分析— SOFAJRaft启动时做了什么?
一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式
解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段