Springboot启动流程
Springboot启动流程
本文使用的SpringBoot版本为:2.7.4
Springboot启动流程(概括)
1、首先创建SpringApplication实例,在构造方法里(初始化属性):
(1)判断Web应用类型是响应式REACTIVE的,还是基于SERVLET的web应用 WebApplicationType
(2)读取spring.factories加载初始化器 ApplicationContextInitializer
(3)读取spring.factories加载监听器 ApplicationListener
2、实例化之后,执行run方法主体:run方法执行流程是基于观察者模式的,整个Springboot的启动流程实际就是各种事件的发布。
(1)获取并启用监听器 ApplicationListener,并发布应用启动事件 SpringApplicationRunListener
(2)准备环境变量,包括系统属性、启动参数以及用户配置的属性 prepareEnvironment方法
(3)创建应用程序上下文 createApplicationContext方法
(5)准备上下文环境 prepareContext方法,执行实现ApplicationContextInitializer接口的类
(6)刷新上下文 refreshContext方法,自动装配和启动tomcat
(7)发布应用启动成功事件
以上是对Springboot应用启动流程的概括总结,下面让我们结合源码具体深入的了解下Springboot的启动流程。
Springboot启动流程(详细)
入口启动类中最主要的就是@SpringBootApplication注解和SpringApplication.run方法。
@SpringBootApplication
public class SpringbootMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootMybatisApplication.class, args);
}
}
@SpringBootApplication注解主要包含以下三个注解:
@Configuration 配置类
@EnableAutoConfiguration 自动装配,将所有符合条件的bean定义加载到IOC容器
@ComponentScan 自动扫描并加载符合条件的组件或bean
1、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));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
准备阶段,首先创建SpringApplication实例,在构造方法里初始化一些属性:
(1)判断Web应用类型:(WebApplicationType)
三种类型:
NONE 不会嵌入Web容器启动
SERVLET 基于Web容器启动
REACTIVE 响应式启动(spring5新特性)
(2)读取spring.factories加载初始化器
在setInitializers方法中,读取spring.factories配置ApplicationContextInitializer接口的实现类到集合中。
(3)读取spring.factories加载监听器
在setListeners方法中,读取spring.factories配置ApplicationListener接口的实现类到集合中。
(4)获取应用启动主类 mainApplicationClass
2、SpringApplication运行阶段
SpringApplication.run方法内容如下:
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
运行阶段,执行run方法主体;run方法执行流程是基于观察者模式的,整个Springboot的启动流程实际就是各种事件的发布。
(1)获取并启用监听器 ApplicationListener,并发布应用启动事件 SpringApplicationRunListener
EventPublishingRunListener监听方法与 Spring Boot 事件对应关系
监听方法 | SpringBoot事件 | 起始版本 |
---|---|---|
starting() | ApplicationStartingEvent | 1.5 |
enviromentPrepared(ConfigurableEnvironment) | ApplicationEnvironmentPreparedEvent | 1.0 |
contextPrepared(ConfigurableApplicationContext) | ||
contextLoaded(ConfigurableApplicationContext) | ApplicationPreparedEvent | 1.0 |
started(ConfigurableApplicationContext) | ApplicationStartedEvent | 2.0 |
running(ConfigurableApplicationContext) | ApplicationReadyEvent | 2.0 |
failed(ConfigurableApplicationContext,Throwable) | ApplicationFailedEvent | 1.0 |
(2)准备环境变量,包括系统属性、启动参数以及用户配置的属性 prepareEnvironment方法
根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableEnvironment 实例:
Web Reactive: StandardEnvironment
Web Servlet: StandardServletEnvironment
非 Web: StandardEnvironment
(3)创建应用程序上下文 createApplicationContext方法
根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableApplicationContext 实例:
Web Reactive: AnnotationConfigReactiveWebServerApplicationContext
Web Servlet: AnnotationConfigServletWebServerApplicationContext
非 Web: AnnotationConfigApplicationContext
(5)准备上下文环境 prepareContext方法,执行实现ApplicationContextInitializer接口的类
(6)刷新上下文 refreshContext方法,自动装配和启动tomcat
(7)刷新上下文后置处理 afterRefresh方法,空方法,供子类重写
(8)发布应用启动成功事件 listeners.started方法
(9)执行自定义的run方法。ApplicationRunner和CommandLineRunner
(完)