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. 就绪阶段:这个阶段的主要目标是确保应用程序已经准备就绪,可以开始接受和处理请求了。
相关推荐
chxii几秒前
Maven 详解(上)
java·maven
李少兄2 分钟前
IntelliJ IDEA 远程调试(Remote Debugging)教程
java·ide·intellij-idea
Kuo-Teng6 分钟前
Leetcode438. 找到字符串中所有字母异位词
java·算法·leetcode
毕设小屋vx ylw28242614 分钟前
Java开发、Java Web应用、前端技术及Vue项目
java·前端·vue.js
TDengine (老段)19 分钟前
TDengine 字符串函数 CHAR 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
float_com30 分钟前
【java基础语法】------ 数组
java
Adellle34 分钟前
2.单例模式
java·开发语言·单例模式
间彧34 分钟前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧38 分钟前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
零雲44 分钟前
java面试:有了解过RocketMq架构么?详细讲解一下
java·面试·java-rocketmq