Spring Boot 完整启动流程详解

 更新时间:2025年09月12日 10:58:00   作者:敬将来的自己  
本文完整解析Spring Boot启动流程的9个核心阶段,结合源码与实战场景,帮助开发者深入理解框架运行机制,感兴趣的朋友跟随小编一起看看吧

本文完整解析 Spring Boot 启动流程的 9 个核心阶段,结合源码与实战场景,帮助开发者深入理解框架运行机制。适用于面试准备和技术原理学习。

一、启动入口:SpringApplication.run()

public static ConfigurableApplicationContext run(Class<?> primarySource, String[] args) {
    return new SpringApplication(primarySource).run(args);
}

二、完整启动流程(9大核心阶段)

阶段1:初始化启动计时器

StopWatch stopWatch = new StopWatch();
stopWatch.start();

阶段2:监听器初始化与启动事件

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(); // 发布ApplicationStartingEvent
  • ​作用​​:通知所有SpringApplicationRunListener启动开始
  • ​扩展点​​:可自定义监听器实现初始化日志、监控等操作

阶段3:环境准备与环境事件

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArgs);
graph TD
    A[创建Environment对象] --> B[加载配置源]
    B --> C[解析Profile配置]
    C --> D[转换配置属性]
    D --> E[发布ApplicationEnvironmentPreparedEvent]

阶段4:打印Banner

Banner printedBanner = printBanner(environment);
  • 默认打印SPRING BOOT字符Logo
  • 支持自定义banner.txt文件或完全禁用

阶段5:创建应用上下文

context = createApplicationContext();

​上下文类型判断逻辑:​

protected ConfigurableApplicationContext createApplicationContext() {
    return switch (this.webApplicationType) {
        case SERVLET -> new AnnotationConfigServletWebServerApplicationContext();
        case REACTIVE -> new AnnotationConfigReactiveWebServerApplicationContext();
        default -> new AnnotationConfigApplicationContext(); // 非Web应用
    };
}

阶段6:上下文预处理

prepareContext(context, environment, listeners, appArgs, printedBanner);

​核心步骤:​

  1. 关联环境配置到上下文
  2. 应用ApplicationContextInitializer扩展点
  3. 发布ApplicationContextInitializedEvent
  4. 注册主配置类(@SpringBootApplication注解类)
  5. 发布ApplicationPreparedEvent

阶段7:★★★ 核心刷新阶段 ★★★

refreshContext(context); // 内部调用Spring的refresh()

​Spring Framework的12步刷新流程:​

public void refresh() {
    // 1. 准备刷新
    prepareRefresh();
    // 2. 获取BeanFactory
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // 3. 准备BeanFactory
    prepareBeanFactory(beanFactory);
    try {
        // 4. 后置处理BeanFactory
        postProcessBeanFactory(beanFactory);
        // 5. ★★★ 执行BeanFactoryPostProcessor(自动配置入口)
        invokeBeanFactoryPostProcessors(beanFactory);
        // 6. 注册BeanPostProcessor
        registerBeanPostProcessors(beanFactory);
        // 7. 初始化消息源
        initMessageSource();
        // 8. 初始化事件广播器
        initApplicationEventMulticaster();
        // 9. ★ Web容器启动关键步骤
        onRefresh();
        // 10. 注册监听器
        registerListeners();
        // 11. ★★★ 实例化所有非延迟单例Bean
        finishBeanFactoryInitialization(beanFactory);
        // 12. 完成刷新
        finishRefresh();
    } catch (BeansException ex) {
        // 异常处理...
    }
}

刷新阶段重点说明:

​自动装配触发点​​(invokeBeanFactoryPostProcessors):

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(
        beanFactory, getBeanFactoryPostProcessors());
    // 这里会处理@SpringBootApplication->加载自动配置类
}

​嵌入式容器启动点​​(onRefresh):

protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer(); // 启动Tomcat/Jetty
    } catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
    }
}

​Bean实例化点​​(finishBeanFactoryInitialization):

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 初始化所有非延迟单例Bean
    beanFactory.preInstantiateSingletons();
}

阶段8:刷新后处理

afterRefresh(context, appArgs);
  • ​默认空方法​​,开发人员可重写实现自定义逻辑
  • 典型应用:初始化数据库数据、启动定时任务等

阶段9:事件通知与Runner执行

stopWatch.stop();
listeners.started(context); // ApplicationStartedEvent
callRunners(context, appArgs); // 执行ApplicationRunner/CommandLineRunner
listeners.running(context); // ApplicationReadyEvent

Runner执行机制:

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList<>();
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    AnnotationAwareOrderComparator.sort(runners);
    for (Object runner : runners) {
        if (runner instanceof ApplicationRunner) {
            ((ApplicationRunner) runner).run(args);
        }
        if (runner instanceof CommandLineRunner) {
            ((CommandLineRunner) runner).run(args.getSourceArgs());
        }
    }
}

三、Spring Boot启动流程全景图

graph TD
    A[SpringApplication.run] --> B[启动计时器]
    B --> C[初始化监听器]
    C --> D[发布StartingEvent]
    D --> E[准备Environment]
    E --> F[打印Banner]
    F --> G[创建上下文]
    G --> H[预处理上下文]
    H --> I[refreshContext核心]
    I --> J[后置处理]
    J --> K[发布StartedEvent]
    K --> L[执行Runner]
    L --> M[发布ReadyEvent]

四、关键技术原理

1. 自动装配机制

  1. 通过@EnableAutoConfiguration引入自动配置
  2. AutoConfigurationImportSelector扫描META-INF/spring.factories
  3. 使用@Conditional系列注解实现条件装配

2. 嵌入式容器启动

  1. ​Servle容器​​:自动探测并初始化Tomcat/Jetty/Undertow
  2. ​Reactive容器​​:支持Netty/Reactor等
  3. ​启动时机​​:在onRefresh()阶段创建WebServer

3. 配置加载顺序

1. 命令行参数
2. 系统环境变量
3. JNDI属性
4. Java系统属性
5. Profile-specific配置(application-{profile}.yml)
6. 主配置文件(application.yml)
7. @Configuration注解的@PropertySource
8. SpringApplication.setDefaultProperties

到此这篇关于Spring Boot 启动流程详解的文章就介绍到这了,更多相关Spring Boot 启动流程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java 入门图形用户界面设计之事件处理上

    Java 入门图形用户界面设计之事件处理上

    图形界面(简称GUI)是指采用图形方式显示的计算机操作用户界面。与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受,本篇精讲Java语言中关于图形用户界面的事件处理
    2022-02-02
  • Spring Cloud Gateway 获取请求体(Request Body)的多种方法

    Spring Cloud Gateway 获取请求体(Request Body)的多种方法

    这篇文章主要介绍了Spring Cloud Gateway 获取请求体(Request Body)的多种方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • java求余的技巧汇总

    java求余的技巧汇总

    这篇文章主要给大家介绍了关于java求余技巧的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • Java实现替换PDF中的字体功能

    Java实现替换PDF中的字体功能

    文档中可通过应用不同的字体来呈现不一样的视觉效果,通过字体来实现文档布局、排版等设计需要。本文将详细为大家介绍如何利用Java实现替换PDF文中的字体,需要的可以参考一下
    2022-03-03
  • Java基础之自动装箱,注解操作示例

    Java基础之自动装箱,注解操作示例

    这篇文章主要介绍了Java基础之自动装箱,注解操作,结合实例形式分析了java拆箱、装箱、静态导入、注释等相关使用技巧,需要的朋友可以参考下
    2019-08-08
  • MyBatis Mapper.xml入参List使用in函数问题

    MyBatis Mapper.xml入参List使用in函数问题

    文章主要讲述了在使用MyBatis的Mapper.xml文件时,如何正确地在in函数中使用List作为入参,作者强调了完整拷贝<if>...</if>格式的重要性,并指出稍微的改动就会导致错误
    2025-02-02
  • SpringBoot实现Logback输出日志到Kafka方式

    SpringBoot实现Logback输出日志到Kafka方式

    本文介绍了如何在SpringBoot应用中通过自定义Appender实现Logback输出日志到Kafka,包括配置maven依赖、Kafka工具类和logback.xml配置
    2025-02-02
  • SpringBoot调用对方webService接口的几种方法示例

    SpringBoot调用对方webService接口的几种方法示例

    平常我们开发调用接口一般会用到几种数据格式,比如有restful的,这个是目前最流行的,也是最简单开发的,还有一种就是webservice数据格式,本文给大家介绍了几种SpringBoot调用对方webService接口的方法,文中有相关的代码示例供大家参考,需要的朋友可以参考下
    2023-11-11
  • Springboot整合GuavaCache缓存过程解析

    Springboot整合GuavaCache缓存过程解析

    这篇文章主要介绍了springboot整合GuavaCache缓存过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java异常处理机制深入理解

    Java异常处理机制深入理解

    如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器
    2022-01-01

最新评论