一、序言
本文简单分析一下 SpringBoot 的启动流程。
二、SpringBoot 启动源码分析
public ConfigurableApplicationContext run(String... args) {// 记录当前时间的纳秒数,用于计算应用程序启动所花费的时间long startTime = System.nanoTime();// 创建一个默认的引导上下文对象DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 声明一个可配置的应用程序上下文对象,并初始化为 nullConfigurableApplicationContext context = null;// 配置 Headless 模式的属性configureHeadlessProperty();// 获取应用程序运行监听器SpringApplicationRunListeners listeners = getRunListeners(args);// 通知监听器应用程序即将启动listeners.starting(bootstrapContext, this.mainApplicationClass);try {// 创建应用程序参数对象ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 准备环境,包括配置文件加载、属性设置等ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 配置环境,忽略 Bean 信息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);// 执行应用程序中的所有 ApplicationRunner 和 CommandLineRunner 实例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;
}
三、SpringBoot 启动流程分析
我们可以将 SpringBoot 启动流程归纳为上面的几个大阶段:
- 初始化和准备阶段:这个阶段包括记录启动时间、创建引导上下文、配置 Headless 属性、获取运行监听器、环境准备以及打印 Banner 等步骤。这个阶段的主要目标是为接下来的步骤做好准备。
- 创建应用程序上下文阶段:这个阶段主要是创建 ApplicationContext 实例,并加载 Bean 定义。这个阶段的主要目标是创建并初始化 Spring 的 IoC 容器。
- 刷新应用程序上下文阶段:这个阶段主要是完成 Bean 的初始化,包括调用初始化方法、完成 Bean 的依赖注入等,以及调用所有的 ApplicationRunner 和 CommandLineRunner 的 run 方法。这个阶段的主要目标是完成应用程序的启动。
- 就绪阶段:这个阶段的主要目标是确保应用程序已经准备就绪,可以开始接受和处理请求了。