03、SpringBoot 启动 执行SpringApplication的run方法 准备运行环境前 流程
目录:Springboot源码学习目录
上文:02、SpringBoot 启动 总流程
前言:本篇文章开始讲;SpringBoot的启动流程的第二部分,当前第二部分是核心逻辑,也分为几块进行讲解,分别是,准备运行环境前,准备运行环境,创建应用上下文,准备应用上下文,刷新应用上下文,刷新应用上下文后处理,本文主要讲解准备运行环境前的一些流程,是一些不太重要的流程,只是把run方法的大体脉络,以及源码展示一下,重点的从下一篇开始
一、启动总流程
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 创建引导上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 配置应用为headless模式
// Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标
configureHeadlessProperty();
// 获取Spring应用运行监听器,这里其实是初始化了一个广播器,将前面获取的所有的监听器注册到广播器中
// 后续的流程中会触发各种事件
SpringApplicationRunListeners listeners = getRunListeners(args);
// 获取Spring应用运行监听器后,立刻发出第一个事件,标志着应用要开始启动了,进行最早的一些初始化工作
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);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
/ 发出启动结束事件,上下文已刷新,应用程序已启动,但尚未调用CommandLineRunner和ApplicationRunner。
listeners.started(context);
// 执行runner的run方法
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 发出运行中事件,此时应用程序上下文已刷新,并且所有CommandLineRunner和ApplicationRunner都已调用
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 返回最终构建的容器对象
return context;
}
二、创建引导上下文
private DefaultBootstrapContext createBootstrapContext() {
// 创建一个DefaultBootstrapContext对象
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
// 前面的文章里提到实例化SpringApplication应用时,初始化了引导注册表初始化后增强器,在这里创建DefaultBootstrapContext对象后,就是对他进行增强的
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
三、获取Spring应用运行监听器
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 创建一个SpringApplicationRunListeners对象,里面里面存放里一个SpringApplicationRunListener(Spring应用程序运行监听器)集合
// 获取的是SpringApplicationRunListener(Spring应用程序运行监听器)的方式和前面文章中
// 应用程序监听器(ApplicationListener),应用程序上下文初始化后增强器(ApplicationContextInitializer),引导注册表初始化后增强器,的获取方法一样,从spring.factories 中获取指定类型的实现类集合
// Spring应用程序运行监听器 和前面的 应用程序监听器 不是一个东西,Spring应用程序运行监听器只会在springboot启动的过程中生效,在启动的各个环节进行一些增强操作
// 有些Spring应用程序运行监听器 中还会初始化一个 广播器,回调应用程序监听器
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}

浙公网安备 33010602011771号