专栏文章
专栏文章
SpringBoot 系列
1. SpringBoot 系列 #01:SpringBoot 启动流程源码分析 2. SpringBoot 系列 #02:SpringBoot 日志集成原理 3. SpringBoot 系列 #03:SpringBoot 自动装配原理

SpringBoot 系列 #01:SpringBoot 启动流程源码分析

发布于 2026-05-26 09:43 👁 9 次阅读
#源码解析#spring#springboot

基于 SpringBoot 2.4.4 源码 + 真实运行日志验证。整体分 5 个阶段:构造 → 启动准备 → 准备 ApplicationContext → 刷新 → 启动完成。每阶段标注扩展点(🔌)和日志验证(✅)。

缩写速查Spring 术语与缩写速查 · 相关笔记Spring 容器启动流程源码分析 · Spring 三级缓存与循环依赖


目录

章节 说明
流程总览 5 阶段结构图
阶段一:构造 SpringApplication WebType 推断、三大组件加载
阶段二:run() 启动准备 事件、Environment、配置文件加载
阶段三:准备 ApplicationContext 创建上下文、BeanDefinition 加载
阶段四:刷新 ApplicationContext Spring IOC 核心、Tomcat 启动
阶段五:启动完成 Runner 回调、就绪事件
扩展点汇总 所有扩展点一览(含典型实现类)
BeanFactory 创建时机与 BeanDefinition 两步加载 BeanFactory 何时创建、种子 BD 如何被展开

流程总览

springboot startup flow

SpringApplication.run(primarySources, args)
  │
  ├─ 阶段一:new SpringApplication
  │     推断 WebType → 加载 Bootstrapper / Initializer / Listener
  │
  ├─ 阶段二:instance.run(args)
  │     BootstrapContext → starting 事件 → prepareEnvironment → Banner
  │
  ├─ 阶段三:prepareContext
  │     createApplicationContext → applyInitializers → load BeanDefinition
  │
  ├─ 阶段四:refreshContext
  │     ShutdownHook → Spring refresh(BFPP → BPP → Bean 实例化 → Tomcat 启动)
  │
  └─ 阶段五:启动完成
        afterRefresh → started 事件 → Runners → ready 事件

阶段一:构造 SpringApplication

入口等同于 new SpringApplication(primarySources).run(args),构造阶段完成 4 件事:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

    // 1. 推断 WebApplicationType(检测类路径)
    this.webApplicationType = WebApplicationType.deduceFromClasspath();

    // 2-4. 通过 spring.factories 加载三大组件
    this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection)   getSpringFactoriesInstances(ApplicationListener.class));

    // 5. 堆栈回溯找到 main() 所在类
    this.mainApplicationClass = deduceMainApplicationClass();
}

1.1 WebApplicationType 推断

检测条件 结果
类路径存在 DispatcherHandler,不存在 DispatcherServlet REACTIVE
类路径存在 Servlet + ConfigurableWebApplicationContext SERVLET
其他 NONE

1.2 Bootstrapper

作用:refresh 前的轻量辅助容器,用于注册创建代价高或需要早期共享的实例。以 Class 为 key,每类型只能存一个。

生命周期prepareContext 阶段调用 bootstrapContext.close(context) 后关闭,非用户扩展 API。

1.3 ApplicationContextInitializer 🔌

作用:在 refresh() 前回调,典型用途是注册额外的 PropertySource 或激活 Profile。

默认加载的 5 个实现(spring.factories):

实现类 功能
ConfigurationWarningsApplicationContextInitializer 检测问题扫描路径(如 org.springframework),打印警告
ContextIdApplicationContextInitializer 设置上下文 ContextId
DelegatingApplicationContextInitializer 读取 context.initializer.classes 属性加载自定义 Initializer
RSocketPortInfoApplicationContextInitializer 将 RSocket Server 端口写入 server.ports
ServerPortInfoApplicationContextInitializer 将 Web Server 端口写入 server.ports

自定义注册方式:① spring.factories 写入;② context.initializer.classes 属性配置。

1.4 ApplicationListener 🔌

作用:观察者模式,监听生命周期事件。默认加载 8 个监听器:

监听器 监听事件 功能
ClearCachesApplicationListener ContextRefreshedEvent 清空反射缓存、ClassLoader 缓存
ParentContextCloserApplicationListener ParentContextAvailableEvent 父上下文关闭时联动关闭子上下文
FileEncodingApplicationListener EnvironmentPreparedEvent 校验 file.encoding 一致性
AnsiOutputApplicationListener EnvironmentPreparedEvent 设置 ANSI 输出
DelegatingApplicationListener EnvironmentPreparedEvent 读取 context.listener.classes 加载自定义监听器
LoggingApplicationListener Starting/Prepared/Closed/Failed 联动 LoggingSystem 生命周期
EnvironmentPostProcessorApplicationListener EnvironmentPreparedEvent 触发配置文件加载(入口)
LiquibaseServiceLocatorApplicationListener ApplicationStartingEvent Liquibase 初始化

阶段二:run() 启动准备

2.1 基础准备

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

DefaultBootstrapContext bootstrapContext = createBootstrapContext(); // 初始化 Bootstrapper
configureHeadlessProperty();  // java.awt.headless=true,服务器无图形界面

2.2 发布 ApplicationStartingEvent

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
// → LoggingApplicationListener 响应:初始化 LoggingSystem
// → LiquibaseServiceLocatorApplicationListener 响应

2.3 prepareEnvironment(配置加载核心)✅ 日志验证

调用链(日志验证顺序):

listeners.environmentPrepared()
  → EnvironmentPostProcessorApplicationListener
  → RandomValuePropertySource 加入 ✅
  → ConfigDataEnvironmentPostProcessor ✅
     → ConfigDataEnvironment(构建属性源贡献者)✅
        → 扫描配置文件位置(见下表)
        → 加载 application.yaml ✅

StandardServletEnvironment 默认属性源(✅ 日志验证):

属性源 内容
systemProperties JVM 系统属性
systemEnvironment OS 环境变量
servletContextInitParams ServletContext 初始化参数 ✅
servletConfigInitParams ServletConfig 初始化参数 ✅
configurationProperties Spring 配置属性绑定 ✅

配置文件扫描位置(优先级从高到低,file 系列高于 classpath)✅ 日志验证:

① file:./config/*/
② file:./config/
③ file:./
④ classpath:/config/
⑤ classpath:/          ← application.yaml 从此处加载 ✅

扩展点:自定义 EnvironmentPostProcessor 🔌

// spring.factories 注册
org.springframework.boot.env.EnvironmentPostProcessor=com.example.MyEnvPostProcessor

public class MyEnvPostProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication app) {
        // 可新增/修改属性源,优先级高于 application.properties
        env.getPropertySources().addFirst(new MapPropertySource("custom", Map.of("key", "value")));
    }
}

阶段三:准备 ApplicationContext

3.1 createApplicationContext ✅ 日志验证

// 按 WebType 创建对应实现(✅ 日志:Refreshing AnnotationConfigServletWebServerApplicationContext)
switch (webApplicationType) {
case SERVLET:   return new AnnotationConfigServletWebServerApplicationContext();
case REACTIVE:  return new AnnotationConfigReactiveWebServerApplicationContext();
default:        return new AnnotationConfigApplicationContext();
}

3.2 prepareContext 执行顺序

context.setEnvironment(environment);          // 将 Environment 注入上下文
postProcessApplicationContext(context);        // 注册 ConversionService / ResourceLoader
applyInitializers(context);                    // 🔌 回调所有 ApplicationContextInitializer
listeners.contextPrepared(context);            // 发布 ContextPreparedEvent
bootstrapContext.close(context);               // 辅助容器关闭
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
load(context, sources.toArray(...));           // 🔌 加载 BeanDefinition(自动装配入口)
listeners.contextLoaded(context);              // 发布 ContextLoadedEvent

3.3 自动装配入口(load 阶段)🔌

load(启动类)
  → 解析 @SpringBootApplication
  → @EnableAutoConfiguration
  → AutoConfigurationImportSelector
  → spring.factories: org.springframework.boot.autoconfigure.EnableAutoConfiguration
  → 按 @Conditional 条件筛选后注册 BeanDefinition

阶段四:刷新 ApplicationContext

4.1 注册 ShutdownHook

context.registerShutdownHook();  // 进程退出时触发 context.close(),Bean 优雅销毁
refresh((ApplicationContext) context);

4.2 AbstractApplicationContext#refresh() ✅ 日志验证

SpringBoot 委托给 Spring Core 的标准刷新流程,6 个关键步骤:

步骤 方法 说明
prepareRefresh() 上下文状态设置,initPropertySources
invokeBeanFactoryPostProcessors() 🔌 ConfigurationClassPostProcessor 解析 @ConfigurationOnClassCondition 批量判断 AutoConfiguration ✅
registerBeanPostProcessors() 🔌 注册 AOP / 事务 BeanPostProcessor
finishBeanFactoryInitialization() 实例化所有非懒加载 Bean,执行 @Autowired / @PostConstruct
onRefresh() 启动内嵌 Tomcat/Netty ✅,注册 Servlet/Filter
publishEvent(ContextRefreshedEvent) 触发 ClearCachesApplicationListener 清空缓存

关键顺序:Tomcat 在 onRefresh() 启动,晚于 Bean 实例化(④),保证所有 Bean 就绪后才开放端口。✅ 日志验证:Root WebApplicationContext: initialization completedTomcat started on port(s): 9999


阶段五:启动完成

afterRefresh(context, applicationArguments);  // 🔌 空实现,可覆写
stopWatch.stop();

listeners.started(context);                   // 发布 ApplicationStartedEvent
callRunners(context, applicationArguments);   // 🔌 回调 Runner
listeners.running(context);                   // 发布 ApplicationReadyEvent(服务就绪)

Runner 执行顺序 🔌

// 两类 Runner 按 @Order 混合排序后依次执行
// ApplicationRunner:封装了 ApplicationArguments(支持 --key=value 解析)
// CommandLineRunner:直接传原始 String[] args
@Component
@Order(1)
public class MyRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        // 上下文已完全就绪,可安全使用所有 Bean
        // 典型用途:数据预热、缓存初始化、健康检查
    }
}

扩展点汇总

扩展点 注册方式 触发时机 典型实现类 典型用途
BootstrapRegistryInitializer spring.factories createBootstrapContext() 自定义实现 refresh 前注册早期共享实例(如远程配置中心连接)
ApplicationListener spring.factories / context.listener.classes 各生命周期事件 LoggingApplicationListener
EnvironmentPostProcessorApplicationListener
ClearCachesApplicationListener
监听启动/停止事件
ApplicationContextInitializer spring.factories / context.initializer.classes refresh 前 ConfigurationWarningsApplicationContextInitializer
ServerPortInfoApplicationContextInitializer
ContextIdApplicationContextInitializer
注册 PropertySource、激活 Profile
EnvironmentPostProcessor spring.factories EnvironmentPreparedEvent ConfigDataEnvironmentPostProcessor(加载 application.yaml)
RandomValuePropertySourceEnvironmentPostProcessor
加密配置解密、外部配置中心
BeanDefinitionRegistryPostProcessor @Component / @Bean / spring.factories invokeBeanFactoryPostProcessors 最先执行 ConfigurationClassPostProcessor(解析 @Configuration / @ComponentScan / @Import) 注册额外 BeanDefinition
BeanFactoryPostProcessor @Component / @Bean invokeBeanFactoryPostProcessors PropertySourcesPlaceholderConfigurer(解析 ${...})
EventListenerMethodProcessor
修改已有 BeanDefinition
BeanPostProcessor @Component / @Bean Bean 实例化前后 AutowiredAnnotationBeanPostProcessor(@Autowired)
CommonAnnotationBeanPostProcessor(@Resource/@PostConstruct)
AbstractAutoProxyCreator(AOP 代理)
AOP 代理、属性注入
ApplicationRunner @Component 所有 Bean 就绪后 自定义实现 数据预热、缓存初始化
CommandLineRunner @Component 所有 Bean 就绪后 自定义实现 同上,args 格式不同
afterRefresh 覆写 继承 SpringApplication refresh 完成后 自定义实现 极少用,Runner 优先
AutoConfiguration spring.factories invokeBeanFactoryPostProcessors 中展开 DataSourceAutoConfiguration
WebMvcAutoConfiguration
JacksonAutoConfiguration
框架自动装配

BeanFactory 创建时机与 BeanDefinition 两步加载

BeanFactory 在哪里创建

BeanFactory prepareContext 之前就已构建完毕,创建时机是 createApplicationContext()

// SpringApplication#run()
context = createApplicationContext();              // ① BeanFactory 在此创建(空)
prepareContext(..., context, ...);                 // ② 往 BeanFactory 注册"种子" BeanDefinition
refreshContext(context);                           // ③ refresh() 展开所有 BeanDefinition

createApplicationContext() 根据 WebApplicationType 选择实现类,其构造器里:

// AnnotationConfigServletWebServerApplicationContext 构造器
public AnnotationConfigServletWebServerApplicationContext() {
    this.reader  = new AnnotatedBeanDefinitionReader(this);  // 注册注解处理器 BD
    this.scanner = new ClassPathBeanDefinitionScanner(this); // 准备组件扫描器
    // 父类 GenericApplicationContext 构造器:
    // this.beanFactory = new DefaultListableBeanFactory(); ← 空 BeanFactory 就绪
}

BeanDefinition 两步加载

Spring Boot 的 BeanDefinition 加载分两步完成,核心桥梁是 ConfigurationClassPostProcessor

第一步(prepareContext → load()):注册"种子"

BeanDefinitionLoader 将 sources 注册为 BeanDefinition,sources 来源包括:

来源 说明
SpringApplication.run(Application.class, args) 传入的启动类 最常见,1 个 @SpringBootApplication BD
new SpringApplication(A.class, B.class) 额外传入的类 多个入口类
SpringApplicationBuilder.sources("classpath:extra.xml") XML 配置文件
ApplicationContextInitializer#initialize() 直接注册 极少,通常在 Initializer 里操作

此阶段只把 Application.class 注册为一个 BD,其上的 @ComponentScan / @Import 尚未展开

第二步(refreshContext → invokeBeanFactoryPostProcessors):展开所有 BD

ConfigurationClassPostProcessor(实现 BeanDefinitionRegistryPostProcessor)拿到第一步的种子 BD,递归解析:

ConfigurationClassPostProcessor#processConfigBeanDefinitions()
  └── 解析 @SpringBootApplication
        ├── @ComponentScan → 扫描所有 @Component/@Service/@Repository
        ├── @EnableAutoConfiguration
        │     └── AutoConfigurationImportSelector
        │           └── spring.factories → 按 @Conditional 筛选 → 注册 AutoConfig BD
        └── @Bean 方法 → 注册方法级 BeanDefinition

完整时序:

createApplicationContext()          BeanFactory 创建(空)
  ↓
prepareContext → load(sources)      注册 Application.class BD(1个种子)
  ↓
refresh → invokeBFPP
  └── ConfigurationClassPostProcessor  展开 @ComponentScan / @Import / @Bean
                                        BeanFactory 中 N 个 BD 全部就绪
  ↓
finishBeanFactoryInitialization()   实例化所有非懒加载 Bean

关键结论prepareContext 阶段 BeanFactory 已存在,但只有"种子";真正的业务 Bean、AutoConfiguration Bean 全部由 ConfigurationClassPostProcessorrefresh() 内完成注册。这就是 Spring Boot 自动装配与 Spring 容器 refresh 流程的衔接点。


参考资料

← 返回列表

评论 (0)

暂无评论,来留下第一条吧。

发表评论