ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

SpringApplication启动流程源码解析

SpringApplication启动流程源码解析
  1. 从main方法的SpringApplication.run()开始,这里是使用类名调用静态方法,这是启动的入口

  2. contrl+b进入源码,看到这个run方法,在这里面这个静态run方法的实现分为两步骤,第一先初始化实例SpringApplication,然后再调用SpringApplication的run方法

2.1 在new SpringApplication中,是通过构造函数进行初始化

在这里SpringBoot会推断web应用类型,是reactive/servlet/none

this.properties.setWebApplicationType(WebApplicationType.deduce());

之后加载 Initializers 和 Listeners: Spring Boot 会从META-INF/spring.factories(在 Spring Boot 3.x 中,主要迁移到了META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,但spring.factories依然为了兼容性而存在)文件中,加载ApplicationContextInitializer和ApplicationListener接口的实现类

this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

2.2 run方法核心步骤讲解

  • Startup机制计时

在SpringBoot2.3及以前,run方法一开始就启动StopWatch来计时,但是现在使用了Startup机制来计时,为什么换了,原因如下?

StopWatch太简单了,只能记录“总耗时”。而在 Spring Boot 3.x 中,开发者需要更细粒度的监控(比如:Environment 准备花了多久?Bean 初始化花了多久?Tomcat 启动花了多久?)。Startup机制引入了一个名为ApplicationStartup的接口,它支持记录启动过程中的每一个步骤(Step),功能比StopWatch强大得多

  • Evironment准备:

prepareEnvironment()方法在容器创建之前执行,负责创建Environment并加载所有配置源。加载顺序(优先级从低到高,后加载的覆盖先加载的)如下:

  1. application.yml/application.properties:最低优先级。

  2. 操作系统环境变量:高于配置文件。

  3. JVM 系统属性(-D参数):高于环境变量。

  4. 命令行参数(--server.port=9090):最高优先级

  • 创建 ApplicationContext:根据 Web 类型选择

Spring Boot 会根据之前在new Application中推断的WebApplicationType,在createApplicationContext()方法中创建对应的容器。

Web 应用类型创建的 ApplicationContext 实现
SERVLETAnnotationConfigServletWebServerApplicationContext
REACTIVEAnnotationConfigReactiveWebServerApplicationContext
NONEAnnotationConfigApplicationContext
  • refreshContext()这里标志着Spring IOC的正式初始化和启动,内部完成了大量工作,会扫描创建装配所有Bean

  • refresh完成后,整个应用就启动完毕了,run方法return ApplicationContext容器

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进