欢迎光临
我们一直在努力

SpringBoot启动流程深度解析:从源码到实战

SpringBoot 启动流程全解析:从源码到面试,一文打通 Bean 生命周期与自动配置

本文将按照真实源码的执行顺序,把 SpringBoot 启动流程、Bean 生命周期、三级缓存、自动配置、SPI 机制、BeanPostProcessor 等核心知识点全部串联起来。无论是应对面试,还是日常排查启动报错,这篇文章都能为你提供清晰的思路。


整体总览:SpringBoot 启动的两大阶段

SpringBoot 的启动过程本质上可以分为两大阶段:

  • SpringApplication 实例化阶段:构造器初始化,准备启动所需的基础组件。
  • run() 方法执行阶段:真正启动容器、加载 Bean、启动 Web 服务。
  • 入口代码永远是这一行:

    @SpringBootApplication
    public class Application {
    public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
    }
    }

    全局启动流程图

    #mermaid-svg-KyWVnsCSaOFNGNOj{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KyWVnsCSaOFNGNOj .error-icon{fill:#552222;}#mermaid-svg-KyWVnsCSaOFNGNOj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KyWVnsCSaOFNGNOj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KyWVnsCSaOFNGNOj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KyWVnsCSaOFNGNOj .marker.cross{stroke:#333333;}#mermaid-svg-KyWVnsCSaOFNGNOj svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KyWVnsCSaOFNGNOj p{margin:0;}#mermaid-svg-KyWVnsCSaOFNGNOj .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-KyWVnsCSaOFNGNOj .cluster-label text{fill:#333;}#mermaid-svg-KyWVnsCSaOFNGNOj .cluster-label span{color:#333;}#mermaid-svg-KyWVnsCSaOFNGNOj .cluster-label span p{background-color:transparent;}#mermaid-svg-KyWVnsCSaOFNGNOj .label text,#mermaid-svg-KyWVnsCSaOFNGNOj span{fill:#333;color:#333;}#mermaid-svg-KyWVnsCSaOFNGNOj .node rect,#mermaid-svg-KyWVnsCSaOFNGNOj .node circle,#mermaid-svg-KyWVnsCSaOFNGNOj .node ellipse,#mermaid-svg-KyWVnsCSaOFNGNOj .node polygon,#mermaid-svg-KyWVnsCSaOFNGNOj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KyWVnsCSaOFNGNOj .rough-node .label text,#mermaid-svg-KyWVnsCSaOFNGNOj .node .label text,#mermaid-svg-KyWVnsCSaOFNGNOj .image-shape .label,#mermaid-svg-KyWVnsCSaOFNGNOj .icon-shape .label{text-anchor:middle;}#mermaid-svg-KyWVnsCSaOFNGNOj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KyWVnsCSaOFNGNOj .rough-node .label,#mermaid-svg-KyWVnsCSaOFNGNOj .node .label,#mermaid-svg-KyWVnsCSaOFNGNOj .image-shape .label,#mermaid-svg-KyWVnsCSaOFNGNOj .icon-shape .label{text-align:center;}#mermaid-svg-KyWVnsCSaOFNGNOj .node.clickable{cursor:pointer;}#mermaid-svg-KyWVnsCSaOFNGNOj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KyWVnsCSaOFNGNOj .arrowheadPath{fill:#333333;}#mermaid-svg-KyWVnsCSaOFNGNOj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KyWVnsCSaOFNGNOj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KyWVnsCSaOFNGNOj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KyWVnsCSaOFNGNOj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KyWVnsCSaOFNGNOj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KyWVnsCSaOFNGNOj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KyWVnsCSaOFNGNOj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KyWVnsCSaOFNGNOj .cluster text{fill:#333;}#mermaid-svg-KyWVnsCSaOFNGNOj .cluster span{color:#333;}#mermaid-svg-KyWVnsCSaOFNGNOj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KyWVnsCSaOFNGNOj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KyWVnsCSaOFNGNOj rect.text{fill:none;stroke-width:0;}#mermaid-svg-KyWVnsCSaOFNGNOj .icon-shape,#mermaid-svg-KyWVnsCSaOFNGNOj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KyWVnsCSaOFNGNOj .icon-shape p,#mermaid-svg-KyWVnsCSaOFNGNOj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KyWVnsCSaOFNGNOj .icon-shape .label rect,#mermaid-svg-KyWVnsCSaOFNGNOj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KyWVnsCSaOFNGNOj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KyWVnsCSaOFNGNOj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KyWVnsCSaOFNGNOj :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    main方法启动

    第一阶段: new SpringApplication

    推断应用类型 Web/None

    加载 ApplicationContextInitializer

    加载 ApplicationListener

    推断主类 MainApplicationClass

    第二阶段: 执行 run 方法

    启动计时器 & 获取监听器

    准备 Environment 环境

    打印 Banner

    创建 ApplicationContext 容器

    预处理上下文

    核心: refresh 刷新容器

    刷新后处理 & 停止计时

    执行 Runner 回调

    发布启动完成事件


    第一阶段:SpringApplication 实例化

    当你调用 run 方法时,底层会先 new 一个 SpringApplication 对象。构造器主要做 4 件事:

    1. 判断应用类型(WebApplicationType)

    Spring 会根据类路径下是否存在特定的类来判断应用类型:

    • SERVLET:存在 Servlet、DispatcherServlet 等类,判定为普通 Web 应用(Spring MVC)。
    • REACTIVE:存在 WebFlux 相关类(如 DispatcherHandler),且不存在 Servlet 类,判定为响应式应用。
    • NONE:无 Web 环境相关类,判定为纯后台应用(如定时任务、消息消费者)。

    2. 加载并设置 ApplicationContextInitializer(容器初始化器)

    通过 Spring 的 SPI 机制,扫描所有 jar 包下的配置文件,找到 key 为 ApplicationContextInitializer 的实现类并保存。

    原理解析:在 Spring Boot 2.7 之前,扫描的是 META-INF/spring.factories;在 Spring Boot 2.7 及 3.x 版本中,自动配置相关的 SPI 文件改为了 META-INF/spring/org.springframework.boot.context.ApplicationContextInitializer.imports。这些初始化器会在容器刷新(refresh)之前被调用,用于对容器进行自定义扩展。

    3. 加载并设置 ApplicationListener(事件监听器)

    同样通过 SPI 机制加载所有事件监听器。Spring 内部定义了一系列事件(如 ApplicationStartingEvent、ApplicationReadyEvent),这些监听器用于在启动的各个节点执行自定义逻辑。

    4. 推断主类(MainApplicationClass)

    通过获取当前线程的堆栈追踪(Stack Trace),找到执行 main 方法的类,也就是你的启动类。这为后续扫描 @SpringBootApplication 提供了基准包路径。


    第二阶段:执行 run() 方法(核心启动流程)

    这是真正的启动过程,按源码执行顺序拆解为 12 个关键步骤。

    步骤 1:启动计时器与获取启动监听器

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

    • 记录启动耗时。
    • 通过 SPI 获取 SpringApplicationRunListener 实现(默认是 EventPublishingRunListener)。
    • 发布 ApplicationStartingEvent(应用开始启动事件)。

    步骤 2:准备应用环境 Environment

    这一步加载所有配置,是整个应用的配置来源。加载顺序决定了配置的优先级(优先级从高到低):

  • 命令行参数(–server.port=8080)
  • Java 系统属性(System.getProperties())
  • 操作系统环境变量(System.getenv())
  • 配置文件(application.properties / application.yml,以及 application-{profile}.yml)
  • 绑定配置到 Spring Environment 对象后,发布 ApplicationEnvironmentPreparedEvent(环境准备完成事件)。

    步骤 3:打印 Banner

    读取项目根目录下的 banner.txt 或默认的 Spring Boot Banner 并打印。无实际业务功能,纯标识作用。

    步骤 4:创建 Spring 容器 ApplicationContext

    根据步骤 1 判断的应用类型,创建对应的 IOC 容器:

    • Servlet Web 应用:创建 AnnotationConfigServletWebServerApplicationContext。
    • 非 Web 应用:创建 AnnotationConfigApplicationContext。

    原理解析:Web 容器继承自非 Web 容器,额外增加了对 Servlet 环境(如 ServletContext)的支持,并能够管理内嵌 Tomcat 的生命周期。

    步骤 5:预处理上下文(前置准备)

    给刚创建的空容器做初始化:

  • 将 Environment 绑定到容器。
  • 执行第一阶段加载的所有 ApplicationContextInitializer。
  • 发布 ApplicationContextInitializedEvent。
  • 将启动类(Main Class)作为配置类注册到容器中。

  • 步骤 6:核心中的核心 —— refresh(context) 刷新容器

    这一步是 Spring 容器的灵魂。refresh() 是 AbstractApplicationContext 的模板方法,内部包含 12 个子步骤。Bean 扫描、自动配置、实例化、AOP 全在这里执行。

    refresh() 内部 12 步拆解

    ① prepareRefresh()

    • 初始化容器状态(标记为 active)。
    • 验证 Environment 中配置的必选属性(通过 @Value("${xxx:#{null}}" 或 environment.setRequiredProperties() 设置)是否存在。

    ② obtainFreshBeanFactory()

    • 刷新内部 BeanFactory。
    • 创建 DefaultListableBeanFactory,这是 Spring IOC 的底层核心实现,后续所有的 Bean 定义和实例都存放在这里。

    ③ prepareBeanFactory(beanFactory)

    • 设置类加载器(ClassLoader)。
    • 添加核心的 BeanPostProcessor:ApplicationContextAwareProcessor(用于处理实现了 ApplicationContextAware 等 Aware 接口的 Bean)。
    • 注册默认的环境 Bean(如 environment、systemProperties)。

    ④ postProcessBeanFactory(beanFactory)

    • 空方法,留给子类扩展。
    • Web 应用会在这里注册 ServletContextAwareProcessor,处理 Web 相关的 Aware 接口。

    ⑤ invokeBeanFactoryPostProcessors(beanFactory) 【自动配置核心】 这是自动配置和 Bean 扫描的关键执行点:

  • 执行内置的 ConfigurationClassPostProcessor(实现了 BeanDefinitionRegistryPostProcessor)。
  • 解析启动类上的 @SpringBootApplication,进而解析 @ComponentScan,扫描包下所有的 @Component/@Service/@Controller。
  • 解析 @Configuration 和 @Bean 配置类。
  • 自动配置加载:通过 AutoConfigurationImportSelector 加载 @EnableAutoConfiguration 引入的所有自动配置类。
  • 根据 @Conditional(如 @ConditionalOnClass)条件判断是否将配置类注册为 Bean。
  • 将所有解析出的类转化为 BeanDefinition,注册到 BeanFactory 中。
  • 概念补充:什么是 BeanDefinition? 它不是 Bean 实例,而是 Bean 的“元数据”或“图纸”。它记录了 Bean 的类名、作用域、是否懒加载、依赖关系等信息。Spring 后续会根据这些图纸来实例化 Bean。

    ⑥ registerBeanPostProcessors(beanFactory)

    • 扫描并注册所有的 BeanPostProcessor(Bean 后置处理器)。
    • 包括处理 @Autowired 的 AutowiredAnnotationBeanPostProcessor,处理 AOP 的 AnnotationAwareAspectJAutoProxyCreator 等。
    • 注意区分:BeanFactoryPostProcessor 作用于 Bean 的定义阶段(修改图纸),而 BeanPostProcessor 作用于 Bean 的实例化阶段(修改成品)。

    ⑦ initMessageSource()

    • 初始化国际化资源(i18n),用于多语言支持。

    ⑧ initApplicationEventMulticaster()

    • 初始化事件广播器。后续容器中发布的所有事件,都由这个广播器分发给对应的 Listener。

    ⑨ onRefresh() 【内嵌 Tomcat 启动】

    • 空方法,留给子类扩展。
    • 对于 Web 应用,ServletWebServerApplicationContext 会重写此方法,在这里创建并启动内嵌的 Tomcat/Jetty/Undertow,并初始化 DispatcherServlet。

    ⑩ registerListeners()

    • 将所有 ApplicationListener 注册到步骤 8 创建的事件广播器中。

    ⑪ finishBeanFactoryInitialization(beanFactory) 【Bean 实例化核心】 这一步实例化所有非懒加载的单例 Bean,你学过的所有 Bean 原理都在这里:

  • 遍历所有 BeanDefinition。
  • 调用 getBean() 开始创建 Bean。
  • 执行 Bean 完整生命周期(详见下方生命周期图)。
  • 利用三级缓存解决循环依赖。
  • 生成 AOP 代理对象。
  • 所有成品 Bean 存入 singletonObjects(一级缓存/单例池)。
  • ⑫ finishRefresh()

    • 清除上下文缓存。
    • 初始化生命周期处理器(LifecycleProcessor)。
    • 发布 ContextRefreshedEvent(容器刷新完成事件)。
    • 正式发布 Web 服务(Tomcat 开始接收外部请求)。

    Bean 生命周期与三级缓存时序图

    为了更清晰地理解步骤 11 中的 Bean 创建过程,请参考以下时序图:

    BeanPostProcessor

    目标 Bean

    BeanFactory

    Spring 容器

    BeanPostProcessor

    目标 Bean

    BeanFactory

    Spring 容器

    #mermaid-svg-wC0eUi2kYJJ1sP0L{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wC0eUi2kYJJ1sP0L .error-icon{fill:#552222;}#mermaid-svg-wC0eUi2kYJJ1sP0L .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wC0eUi2kYJJ1sP0L .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wC0eUi2kYJJ1sP0L .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wC0eUi2kYJJ1sP0L .marker.cross{stroke:#333333;}#mermaid-svg-wC0eUi2kYJJ1sP0L svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wC0eUi2kYJJ1sP0L p{margin:0;}#mermaid-svg-wC0eUi2kYJJ1sP0L .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-wC0eUi2kYJJ1sP0L text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-wC0eUi2kYJJ1sP0L .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-wC0eUi2kYJJ1sP0L .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-wC0eUi2kYJJ1sP0L .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-wC0eUi2kYJJ1sP0L .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-wC0eUi2kYJJ1sP0L #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-wC0eUi2kYJJ1sP0L .sequenceNumber{fill:white;}#mermaid-svg-wC0eUi2kYJJ1sP0L #sequencenumber{fill:#333;}#mermaid-svg-wC0eUi2kYJJ1sP0L #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-wC0eUi2kYJJ1sP0L .messageText{fill:#333;stroke:none;}#mermaid-svg-wC0eUi2kYJJ1sP0L .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-wC0eUi2kYJJ1sP0L .labelText,#mermaid-svg-wC0eUi2kYJJ1sP0L .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-wC0eUi2kYJJ1sP0L .loopText,#mermaid-svg-wC0eUi2kYJJ1sP0L .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-wC0eUi2kYJJ1sP0L .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-wC0eUi2kYJJ1sP0L .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-wC0eUi2kYJJ1sP0L .noteText,#mermaid-svg-wC0eUi2kYJJ1sP0L .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-wC0eUi2kYJJ1sP0L .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-wC0eUi2kYJJ1sP0L .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-wC0eUi2kYJJ1sP0L .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-wC0eUi2kYJJ1sP0L .actorPopupMenu{position:absolute;}#mermaid-svg-wC0eUi2kYJJ1sP0L .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-wC0eUi2kYJJ1sP0L .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-wC0eUi2kYJJ1sP0L .actor-man circle,#mermaid-svg-wC0eUi2kYJJ1sP0L line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-wC0eUi2kYJJ1sP0L :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    若发现循环依赖,从三级缓存获取早期引用,

    并移入二级缓存 (earlySingletonObjects)

    AOP 代理在此阶段生成

    getBean("targetBean")

    1. 实例化 Bean (调用构造器)

    2. 将 ObjectFactory 放入三级缓存 (singletonFactories)

    3. 属性填充 (populateBean)

    4. 调用 Aware 接口方法 (BeanNameAware 等)

    5. 初始化前 (postProcessBeforeInitialization)

    返回处理后的 Bean

    6. 执行初始化方法 (@PostConstruct, InitializingBean, init-method)

    7. 初始化后 (postProcessAfterInitialization)

    返回代理对象或原对象

    8. 将最终成品放入一级缓存 (singletonObjects)

    9. 清理二级、三级缓存

    返回最终的 Bean 实例

    步骤 7:刷新后处理 postProcessAfterRefresh()

    默认空实现,留给子类在容器刷新完成后进行自定义扩展。

    步骤 8:停止计时器,打印启动耗时

    Started Application in 1.53 seconds (JVM running for 2.1)

    步骤 9:执行 ApplicationRunner 与 CommandLineRunner

    所有实现了这两个接口的 Bean,会在容器完全启动后、接收外部请求前执行。常用于项目启动后加载字典数据、初始化缓存、校验配置等。

    • 执行顺序:可以通过 @Order 注解控制。
    • 区别:CommandLineRunner 接收原始的 String[] args 参数;ApplicationRunner 接收封装后的 ApplicationArguments 对象,支持解析 –key=value 格式的参数。

    步骤 10:发布 ApplicationStartedEvent

    发布应用已启动成功事件,通知所有监听器。

    步骤 11:检查是否有异常

    如果启动过程中捕获到异常,发布 ApplicationFailedEvent,并抛出异常终止应用。

    步骤 12:返回就绪的 ApplicationContext

    启动完成,返回 IOC 容器,应用正式对外提供服务。


    核心知识点对应关系表

    为了帮你把零散的知识点串联起来,请参考下表:

    启动步骤对应核心原理 / 面试考点
    构造器初始化 Spring SPI 机制(spring.factories / .imports)、应用类型推断
    prepareEnvironment 配置加载优先级、多环境配置(Profiles)原理
    invokeBeanFactoryPostProcessors 自动配置原理(@EnableAutoConfiguration)、@Conditional 条件注解、BeanDefinition 概念
    registerBeanPostProcessors BeanPostProcessor 与 BeanFactoryPostProcessor 的区别、AOP 处理器注册
    onRefresh 内嵌 Tomcat 启动原理、Spring Boot 为什么不需要外部部署
    finishBeanFactoryInitialization Bean 生命周期、三级缓存解决循环依赖、AOP 动态代理生成时机
    执行 Runner ApplicationRunner 与 CommandLineRunner 的使用场景与区别

    总结

    白话文通俗总结(最易记忆)

  • 认清身份:先搞清楚自己是 Web 应用还是普通应用。
  • 准备粮草:加载所有配置(yml、命令行、环境变量)。
  • 建好空房:创建一个空的 IOC 容器。
  • 绘制图纸:扫描所有 Bean 和自动配置(SPI),生成 BeanDefinition。
  • 准备工具:注册所有 Bean 后置处理器(准备处理 Autowired、AOP、事务)。
  • 启动引擎:启动内嵌 Tomcat。
  • 生产产品:批量实例化所有单例 Bean,走生命周期、解决循环依赖、生成 AOP 代理。
  • 收尾工作:执行启动后的回调 Runner。
  • 开门迎客:发布启动成功事件,服务正式就绪。
  • 面试高频“一句话总结”

    “SpringBoot 启动就是:先准备 Environment 环境,再创建 IOC 容器;通过 SPI 机制加载自动配置类并扫描组件生成 BeanDefinition;接着注册 BeanPostProcessor;然后在 onRefresh 中启动内嵌 Tomcat;最后在 finishBeanFactoryInitialization 中批量实例化单例 Bean,期间通过三级缓存解决循环依赖并生成 AOP 代理,最终发布启动成功事件对外提供服务。”

    掌握以上流程,不仅能让你在面试中对答如流,在遇到 BeanCreationException、CircularReference 或自动配置失效等启动报错时,也能迅速定位到是哪个阶段、哪个后置处理器出了问题。

    赞(0)
    未经允许不得转载:171主机测评 » SpringBoot启动流程深度解析:从源码到实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址