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. 就绪阶段:这个阶段的主要目标是确保应用程序已经准备就绪,可以开始接受和处理请求了。
相关推荐
信徒_18 分钟前
go 语言中的线程池
开发语言·后端·golang
Pandaconda19 分钟前
【Golang 面试题】每日 3 题(六十五)
开发语言·经验分享·笔记·后端·面试·golang·go
至暗时刻darkest20 分钟前
go 查看版本
开发语言·后端·golang
JIU_WW21 分钟前
jar、war、pom
java·jar
向哆哆33 分钟前
Java与NoSQL数据库的集成与优化
java·开发语言·nosql
茂茂在长安36 分钟前
Linux 命令大全完整版(11)
java·linux·运维·服务器·前端·centos
songbaoxian1 小时前
ElasticSearch
java·linux·elasticsearch
非 白1 小时前
【Java】代理模式
java·开发语言·代理模式
muxue1781 小时前
go:运行第一个go语言程序
开发语言·后端·golang
米饭好好吃.1 小时前
【Go】Go wire 依赖注入
开发语言·后端·golang