SpringBoot 启动分析

一、序言

本文简单分析一下 SpringBoot 的启动流程。

二、SpringBoot 启动源码分析

java 复制代码
public ConfigurableApplicationContext run(String... args) {
    // 记录当前时间的纳秒数,用于计算应用程序启动所花费的时间
    long startTime = System.nanoTime();
    // 创建一个默认的引导上下文对象
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    // 声明一个可配置的应用程序上下文对象,并初始化为 null
    ConfigurableApplicationContext 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 启动流程归纳为上面的几个大阶段:

  1. 初始化和准备阶段:这个阶段包括记录启动时间、创建引导上下文、配置 Headless 属性、获取运行监听器、环境准备以及打印 Banner 等步骤。这个阶段的主要目标是为接下来的步骤做好准备。
  2. 创建应用程序上下文阶段:这个阶段主要是创建 ApplicationContext 实例,并加载 Bean 定义。这个阶段的主要目标是创建并初始化 Spring 的 IoC 容器。
  3. 刷新应用程序上下文阶段:这个阶段主要是完成 Bean 的初始化,包括调用初始化方法、完成 Bean 的依赖注入等,以及调用所有的 ApplicationRunner 和 CommandLineRunner 的 run 方法。这个阶段的主要目标是完成应用程序的启动。
  4. 就绪阶段:这个阶段的主要目标是确保应用程序已经准备就绪,可以开始接受和处理请求了。
相关推荐
寻星探路5 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
想用offer打牌6 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
曹牧7 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX7 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
爬山算法8 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7258 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎8 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄8 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea