前言
作为Java程序员,我们必不可少的技术就是Spring了,对于Spring来说,SpringBoot也是把他推到一代神的一个框架,与其说他是一个框架,其实可以说他是一个脚手架,今天我们来学习一下SpringBoot的启动流程,以及核心方法run
。
SpringBoot的启动流程
- 入口类Application中main方法作为程序的主入口
- 调用SpringApplication的静态方法run方法
- 创建一个SpringApplication的实例对象,调用实例对象的run方法
- 查询并加载SpringApplication监听器,并通知这些监听器将要执行
- 创建并准备SpringBoot需要使用的环境
- 进行ApplicationContext的初始化
- 通过@EnableAutoConfigruation注解,将所需要配置加载到IOC容器中,也就是ApplicationContext
- 进行ApplicationContext的刷新操作,让IOC容器变成可用状态
- 再次进行ApplicationContext的刷新操作,这一步主要是为了检查是否有扩展功能
- 启动完毕
run方法
SpringBoot版本:2.7.2
//SpringBoot最终调用的run方法
public ConfigurableApplicationContext run(String... args) {
//计时器用于计时
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
//设置java.awt.headless 属性是true还是false ,默认为true
configureHeadlessProperty();
//获取所有在构造器中读取加载的监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
//启动监听器
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//将args参数封装为ApplicationArguments对象
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//生成一个环境变量,也就是准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
//进行环境的初始化,也就是创建环境
configureIgnoreBeanInfo(environment);
//打印Banner
Banner printedBanner = printBanner(environment);
//ApplicationContext的初始化
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//刷新ApplicationContext前的准备工作
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//ApplicaitonContext的刷新,将IOC变为可用状态
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);
//执行所有的runner
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;
}