Spring Boot 启动流程?

2025年 阅读约 15 分钟 面试指南 · Spring Boot

深入解析Spring Boot启动流程:SpringApplication.run()源码分析、ApplicationContext初始化、事件监听机制、WebServer启动,附面试模拟问答。

一句话总结

Spring Boot 启动流程核心步骤:1)创建 SpringApplication(推断应用类型、加载 Initializer/Listener)→ 2)run() 方法(启动计时、创建 Environment、打印 Banner、创建 ApplicationContext、准备上下文、刷新上下文、启动 WebServer、执行 Runner)。最核心的是 refresh() 方法(Bean 的完整生命周期),以及 事件监听机制(ApplicationEvent 贯穿整个启动过程)。

初级理解

启动入口

# 标准启动类 @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } # run() 方法做了两件事: # 1. new SpringApplication(primarySources) — 创建实例 # 2. run(args) — 执行启动

启动流程概览

# SpringApplication.run() 核心步骤(简化) public ConfigurableApplicationContext run(String... args) { // 1. 启动计时器 StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 2. 创建 BootstrapContext DefaultBootstrapContext bootstrapContext = createBootstrapContext(); // 3. 设置 java.awt.headless configureHeadlessProperty(); // 4. 获取 SpringApplicationRunListeners SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(bootstrapContext); // 5. 解析命令行参数 ApplicationArguments appArgs = new DefaultApplicationArguments(args); // 6. 准备 Environment ConfigurableEnvironment env = prepareEnvironment(listeners, bootstrapContext, appArgs); // 7. 打印 Banner Banner printedBanner = printBanner(env); // 8. 创建 ApplicationContext context = createApplicationContext(); // 9. 准备 ApplicationContext prepareContext(bootstrapContext, context, env, listeners, appArgs, printedBanner); // 10. 刷新 ApplicationContext(核心!) refreshContext(context); // 11. 启动后处理 afterRefresh(context, appArgs); // 12. 执行 Runner callRunners(context, appArgs); return context; }

中级深入

推断应用类型

# SpringApplication 构造时推断应用类型 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.webApplicationType = WebApplicationType.deduceFromClasspath(); // ... } # 三种类型 # NONE:非 Web 应用(普通 Java 应用) # SERVLET:Servlet Web 应用(Spring MVC) # REACTIVE:响应式 Web 应用(WebFlux) # 推断逻辑:检查 classpath 中是否存在特定类 # 有 DispatcherServlet → SERVLET # 有 DispatcherHandler 且无 DispatcherServlet → REACTIVE # 都没有 → NONE

refresh() 方法 — Bean 生命周期核心

# AbstractApplicationContext.refresh() 核心步骤 public void refresh() { // 1. 准备刷新:设置启动时间、状态 prepareRefresh(); // 2. 获取 BeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 3. 准备 BeanFactory:设置类加载器、添加后置处理器 prepareBeanFactory(beanFactory); // 4. 允许子类后置处理 BeanFactory postProcessBeanFactory(beanFactory); // 5. 调用 BeanFactoryPostProcessor(处理 @Configuration) invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册 BeanPostProcessor registerBeanPostProcessors(beanFactory); // 7. 初始化 MessageSource(国际化) initMessageSource(); // 8. 初始化事件广播器 initApplicationEventMulticaster(); // 9. 子类刷新(Spring Boot 在此启动 WebServer) onRefresh(); // 10. 注册监听器 registerListeners(); // 11. 实例化所有非懒加载单例 Bean finishBeanFactoryInitialization(beanFactory); // 12. 完成刷新:发布 ContextRefreshedEvent finishRefresh(); }

高级拓展

事件监听机制

# Spring Boot 启动过程中发布的事件(按顺序) # 1. ApplicationStartingEvent — 启动开始 # 2. ApplicationEnvironmentPreparedEvent — Environment 准备完成 # 3. ApplicationContextInitializedEvent — ApplicationContext 创建完成 # 4. ApplicationPreparedEvent — ApplicationContext 准备完成(refresh 前) # 5. ApplicationStartedEvent — refresh 完成,但 Runner 未执行 # 6. ApplicationReadyEvent — Runner 执行完毕,应用就绪 # 7. ApplicationFailedEvent — 启动失败 # 自定义监听器 @Component public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> { @Override public void onApplicationEvent(ApplicationReadyEvent event) { System.out.println("应用启动完成!"); } } # 或使用 @EventListener @Component public class MyListener { @EventListener public void onReady(ApplicationReadyEvent event) { System.out.println("应用启动完成!"); } }

WebServer 启动时机

# WebServer 在 onRefresh() 中启动 # ServletWebServerApplicationContext.onRefresh() protected void onRefresh() { super.onRefresh(); createWebServer(); // 创建并启动 Tomcat/Jetty/Undertow } # createWebServer() 流程 # 1. 获取 ServletWebServerFactory(TomcatServletWebServerFactory) # 2. 通过工厂创建 WebServer # 3. 启动 WebServer(监听端口) # 4. 发布 ServletWebServerInitializedEvent

实战场景

场景:启动时初始化数据

# 方式1:CommandLineRunner @Component @Order(1) public class DataInitializer implements CommandLineRunner { @Override public void run(String... args) { // 初始化数据 } } # 方式2:ApplicationRunner(推荐,参数更结构化) @Component @Order(2) public class CacheWarmer implements ApplicationRunner { @Override public void run(ApplicationArguments args) { // 预热缓存 } } # 方式3:@PostConstruct @Component public class ConfigLoader { @PostConstruct public void init() { // 注意:此时 Bean 已初始化,但应用可能未完全就绪 } }

面试模拟

面试官:Spring Boot 启动流程是怎样的?

你:核心是 SpringApplication.run()。先创建 SpringApplication 实例(推断应用类型、加载 Initializer/Listener),然后执行 run 方法:创建 Environment → 打印 Banner → 创建 ApplicationContext → prepareContext(注册配置类、加载 Bean)→ refreshContext(Bean 生命周期核心,包括 BeanFactoryPostProcessor、BeanPostProcessor、实例化单例 Bean)→ 启动 WebServer → 执行 Runner。整个过程通过事件机制串联。

面试官:refresh() 方法做了什么?

你:refresh() 是 Spring IoC 容器的核心方法,共 12 步:prepareRefresh → obtainFreshBeanFactory → prepareBeanFactory → postProcessBeanFactory → invokeBeanFactoryPostProcessors(处理 @Configuration)→ registerBeanPostProcessors → initMessageSource → initApplicationEventMulticaster → onRefresh(Spring Boot 在此启动 WebServer)→ registerListeners → finishBeanFactoryInitialization(实例化所有单例 Bean)→ finishRefresh。