启动流程
Spring Boot 的入口是 SpringApplication.run(),它完成环境准备、容器创建、Bean 加载、自动配置、嵌入式服务器启动等一系列工作。
整体流程
main()
└── SpringApplication.run(Application.class, args)
│
├─ 1. 创建 SpringApplication 实例
│ 确定应用类型(SERVLET / REACTIVE / NONE)
│ 加载 SpringApplicationRunListener(SPI)
│
├─ 2. 发布 starting 事件
│
├─ 3. 准备 Environment
│ 加载 application.yml / 环境变量 / 命令行参数
│ 发布 environmentPrepared 事件
│
├─ 4. 打印 Banner
│
├─ 5. 创建 ApplicationContext
│ SERVLET → AnnotationConfigServletWebServerApplicationContext
│
├─ 6. 准备 ApplicationContext
│ 注册 BeanDefinition(@SpringBootApplication 扫描)
│ 发布 contextPrepared 事件
│
├─ 7. 刷新容器 refreshContext()
│ 加载所有 BeanDefinition
│ 执行自动配置(@EnableAutoConfiguration)
│ 实例化所有单例 Bean
│ 启动嵌入式 Web 服务器(Tomcat)
│ 发布 contextRefreshed 事件
│
├─ 8. 发布 started 事件
│
├─ 9. 执行 Runner
│ ApplicationRunner.run()
│ CommandLineRunner.run()
│
└─ 10. 发布 ready 事件(应用就绪)
关键阶段详解
阶段 3:Environment 准备
ConfigurableEnvironment 聚合了所有配置源(PropertySource),按优先级排列后统一查询。配置优先级详见 配置管理。
// 监听 Environment 准备完成事件,可在此修改配置
@Component
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment env,
SpringApplication app) {
// 动态添加配置源(如从数据库、配置中心加载)
Map<String, Object> props = new HashMap<>();
props.put("custom.key", "value");
env.getPropertySources().addFirst(
new MapPropertySource("custom", props));
}
}需在 META-INF/spring.factories 中注册(Spring Boot 3.x 用 META-INF/spring/org.springframework.boot.env.EnvironmentPostProcessor)。
阶段 7:refreshContext
这是最重的阶段,调用 AbstractApplicationContext.refresh(),包含 12 个步骤:
refresh()
├── prepareRefresh() 初始化属性源
├── obtainFreshBeanFactory() 获取/创建 BeanFactory
├── prepareBeanFactory() 配置 BeanFactory(ClassLoader、后处理器等)
├── postProcessBeanFactory() 子类扩展点
├── invokeBeanFactoryPostProcessors() 执行 BeanFactoryPostProcessor
│ 包含 ConfigurationClassPostProcessor → 扫描 @Component、处理 @Import
│ → 执行自动配置(AutoConfigurationImportSelector)
├── registerBeanPostProcessors() 注册 BeanPostProcessor
├── initMessageSource() 国际化
├── initApplicationEventMulticaster()
├── onRefresh() 启动嵌入式 Web 服务器(Tomcat)
├── registerListeners()
├── finishBeanFactoryInitialization() 实例化所有非懒加载单例 Bean
└── finishRefresh() 发布 ContextRefreshedEvent
自动配置加载机制详见 自动配置,Bean 实例化过程详见 Bean生命周期。
阶段 9:Runner 回调
SpringApplication.run() 返回前,按 @Order 顺序执行所有 Runner:
// ApplicationRunner:参数封装为 ApplicationArguments
@Component
@Order(1)
public class DataInitRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
if (args.containsOption("init-data")) {
dataService.initSeedData();
}
log.info("数据初始化完成");
}
}
// CommandLineRunner:参数为原始字符串数组
@Component
@Order(2)
public class CacheWarmupRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
cacheService.warmup();
log.info("缓存预热完成");
}
}Runner 在嵌入式服务器启动之后执行,此时应用已可接收请求,适合预热缓存、初始化数据、注册服务到注册中心等操作。
启动扩展点汇总
| 扩展点 | 时机 | 典型用途 |
|---|---|---|
EnvironmentPostProcessor | Environment 准备后 | 动态注入配置源 |
BeanDefinitionRegistryPostProcessor | BeanDefinition 加载后,实例化前 | 动态注册 Bean |
BeanFactoryPostProcessor | 同上(更通用) | 修改 Bean 定义属性 |
BeanPostProcessor | 每个 Bean 初始化前后 | AOP 代理、属性注入 |
@PostConstruct | Bean 依赖注入完成后 | 单 Bean 的初始化逻辑 |
InitializingBean.afterPropertiesSet | 同上 | 框架风格的初始化 |
ApplicationListener<ContextRefreshedEvent> | 容器刷新完成 | 所有 Bean 就绪后的逻辑 |
ApplicationRunner / CommandLineRunner | 服务器启动后 | 缓存预热、数据初始化 |
SmartLifecycle | 服务器启动后(可控顺序) | 启动/停止时的有序资源管理 |
Bean 初始化顺序
构造函数
→ 依赖注入(@Autowired / setter)
→ BeanPostProcessor.postProcessBeforeInitialization
→ @PostConstruct
→ InitializingBean.afterPropertiesSet
→ @Bean(initMethod = "init")
→ BeanPostProcessor.postProcessAfterInitialization
优雅停机
收到 SIGTERM
→ SmartLifecycle.stop()(按 phase 倒序)
→ DisposableBean.destroy()
→ @PreDestroy
→ DestroyMethod
优雅停机配置详见 优雅停机。
启动事件监听
@Component
public class AppEventListener {
// 容器刷新完成(所有 Bean 已就绪,服务器已启动)
@EventListener(ApplicationReadyEvent.class)
public void onReady(ApplicationReadyEvent event) {
log.info("应用启动完毕,端口: {}",
event.getApplicationContext()
.getEnvironment().getProperty("server.port"));
}
// 容器关闭前
@EventListener(ContextClosedEvent.class)
public void onClose() {
log.info("应用正在关闭...");
}
}事件机制详见 事件机制。
启动耗时分析
Spring Boot 2.5+ 内置了启动耗时分析,通过 Actuator 暴露:
management:
endpoints:
web:
exposure:
include: startup# 获取各阶段启动耗时(需使用 BufferingApplicationStartup)
curl http://localhost:8080/actuator/startup// Application 启动类中启用
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);
}
}减少启动时间的常见手段:
spring.main.lazy-initialization=true(延迟初始化,首次请求时再创建 Bean)- 减少
@ComponentScan范围(精确指定 basePackages) - GraalVM 原生编译(AOT,启动降至毫秒级)详见 GraalVM原生编译