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. 就绪阶段:这个阶段的主要目标是确保应用程序已经准备就绪,可以开始接受和处理请求了。
相关推荐
_Evan_Yao7 分钟前
RAG中的“Chunk”艺术:我试过10种切分策略后总结的结论
java·人工智能·后端·python·软件工程
今天你TLE了吗13 分钟前
LLM到Agent&RAG——AI概念概述 第二章:提示词
人工智能·笔记·后端·学习
魂梦翩跹如雨43 分钟前
数据库的“契约” —— 约束(Constrains)
java·数据库·mysql
独自破碎E1 小时前
面试官:你有用过Java的流式吗?比如说一个列表.stream这种,然后以流式去处理数据。
java·开发语言
IT_陈寒1 小时前
Vue的响应式把我坑惨了,原来问题出在这
前端·人工智能·后端
shark22222221 小时前
能懂!基于Springboot的用户增删查改(三层设计模式)
spring boot·后端·设计模式
2601_949818091 小时前
头歌答案--爬虫实战
java·前端·爬虫
2601_949817922 小时前
大厂Java进阶面试解析笔记文档
java·笔记·面试
郭wes代码2 小时前
大三Java课设:一行行敲出来的贪吃蛇,老师以为我是CV的
java·开发语言
IGAn CTOU2 小时前
王炸级更新!Spring Boot 3.4 正式发布,新特性真香!
java·spring boot·后端