一句话总结
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。