Spring Boot启动过程: 从new SpringApplication到run(),这中间到底发生了什么?
Spring Boot启动过程: 从new SpringApplication到run(),这中间到底发生了什么?
引言: 一行代码背后的千山万水
每个Spring Boot应用的入口都是这样一行代码:
SpringApplication.run(Application.class, args);看似简单,背后却是Spring团队十余年的设计积累。从推断应用类型到加载自动配置,从启动内嵌Web服务器到刷新应用上下文,整个过程涉及数十个步骤和扩展点。
理解这个启动流程,不仅能让你在面试中对答如流,更能在排查启动故障、优化启动性能、扩展框架功能时游刃有余。
本文将完整的启动过程拆解为11个关键步骤,配合源码分析和时序图,让你彻底掌握Spring Boot的启动魔法。
一、启动流程全景图
二、两大阶段: 构造与运行
三、详细步骤拆解
3.1 步骤1: 推断应用类型
/** * SpringApplication 构造器中第一步: 推断应用类型 */ public class Step1_InferApplicationType { // 源码位置: SpringApplication.deduceWebApplicationType() // // private WebApplicationType deduceWebApplicationType() { // // 检查类路径中是否存在特定类 // if (ClassUtils.isPresent( // "org.springframework.web.reactive.DispatcherHandler", null) // && !ClassUtils.isPresent( // "org.springframework.web.servlet.DispatcherServlet", null)) { // return WebApplicationType.REACTIVE; // WebFlux // } // for (String className : SERVLET_INDICATOR_CLASSES) { // if (!ClassUtils.isPresent(className, null)) { // return WebApplicationType.NONE; // 非Web应用 // } // } // return WebApplicationType.SERVLET; // Servlet Web(默认) // } public static void main(String[] args) { System.out.println("=== 推断应用类型 ===\n"); System.out.println("判断逻辑:"); System.out.println("1. 有 DispatcherHandler 且无 DispatcherServlet"); System.out.println(" -> REACTIVE (WebFlux应用)"); System.out.println("2. 缺少 javax.servlet.Servlet 或 DispatcherServlet"); System.out.println(" -> NONE (非Web应用)"); System.out.println("3. 其他情况"); System.out.println(" -> SERVLET (传统Servlet Web应用)\n"); System.out.println("这个判断决定了:"); System.out.println("- 创建哪种 ApplicationContext"); System.out.println("- 是否启动内嵌Web服务器"); System.out.println("- 加载哪些Web相关的自动配置"); } }3.2 步骤2-3: 加载初始化器与监听器(SPI机制)
/** * SpringApplication 构造器第二步、第三步 * 通过 SpringFactoriesLoader 加载初始化器和监听器 */ public class Step2_LoadInitializersAndListeners { // 源码位置: SpringApplication 构造器 // // public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { // this.resourceLoader = resourceLoader; // this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // this.webApplicationType = deduceWebApplicationType(); // // // 步骤2: 从spring.factories加载初始化器 // this.bootstrapRegistryInitializers = // getBootstrapRegistryInitializersFromSpringFactories(); // setInitializers( // getSpringFactoriesInstances(ApplicationContextInitializer.class)); // // // 步骤3: 从spring.factories加载监听器 // setListeners( // getSpringFactoriesInstances(ApplicationListener.class)); // // // 步骤4: 推断主类 // this.mainApplicationClass = deduceMainApplicationClass(); // } public static void main(String[] args) { System.out.println("=== 加载初始化器与监听器 ===\n"); System.out.println("加载机制: SpringFactoriesLoader"); System.out.println("从所有jar包的 META-INF/spring.factories 中读取\n"); System.out.println("spring-boot.jar!/META-INF/spring.factories 内容:"); System.out.println("ApplicationContextInitializer:\\"); System.out.println(" org.springframework.boot.context."); System.out.println(" ConfigurationWarningsApplicationContextInitializer,\\"); System.out.println(" org.springframework.boot.context."); System.out.println(" ContextIdApplicationContextInitializer,\\"); System.out.println(" ...\n"); System.out.println("ApplicationListener:\\"); System.out.println(" org.springframework.boot.context.config."); System.out.println(" ConfigFileApplicationListener,\\"); System.out.println(" org.springframework.boot.context.logging."); System.out.println(" LoggingApplicationListener,\\"); System.out.println(" ...\n"); System.out.println("这些组件在启动各阶段被回调,实现功能扩展"); } }3.3 步骤4: 推断主类
/** * 推断主类: 通过调用栈找到main方法所在的类 */ public class Step4_DeduceMainClass { // 源码逻辑: // private Class<?> deduceMainApplicationClass() { // try { // StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); // for (StackTraceElement element : stackTrace) { // if ("main".equals(element.getMethodName())) { // return Class.forName(element.getClassName()); // } // } // } catch (ClassNotFoundException e) { // // 忽略 // } // return null; // } public static void main(String[] args) { System.out.println("=== 推断主类 ===\n"); System.out.println("方法: 创建一个RuntimeException,分析调用栈"); System.out.println("查找: 栈中包含 'main' 方法的类"); System.out.println("结果: 就是 @SpringBootApplication 标注的类\n"); System.out.println("作用:"); System.out.println("- 作为primarySources传递给ApplicationContext"); System.out.println("- 用于日志输出和Banner信息"); } }3.4 步骤5: 准备环境
/** * run() 方法中的关键步骤: 准备Environment */ public class Step5_PrepareEnvironment { // 源码: SpringApplication.prepareEnvironment() // // private ConfigurableEnvironment prepareEnvironment( // SpringApplicationRunListeners listeners, // DefaultBootstrapContext bootstrapContext, // ApplicationArguments applicationArguments) { // // // 5.1 创建Environment // ConfigurableEnvironment environment = getOrCreateEnvironment(); // // // 5.2 配置Environment // configureEnvironment(environment, applicationArguments.getSourceArgs()); // // // 5.3 将"spring.main"的配置绑定到SpringApplication // ConfigurationPropertySources.attach(environment); // // // 5.4 发布环境准备事件 // listeners.environmentPrepared(bootstrapContext, environment); // // // 5.5 将"spring.main"配置应用到SpringApplication // DefaultPropertiesPropertySource.moveToEnd(environment); // // return environment; // } public static void main(String[] args) { System.out.println("=== 准备Environment ===\n"); System.out.println("子步骤:"); System.out.println("5.1 创建Environment(Standard或Reactive)"); System.out.println("5.2 配置PropertySources和Profiles"); System.out.println(" - 读取命令行参数(--server.port=8080)"); System.out.println(" - 设置激活的Profile(spring.profiles.active)"); System.out.println("5.3 附加ConfigurationPropertySources"); System.out.println("5.4 发布ApplicationEnvironmentPreparedEvent"); System.out.println(" -> ConfigFileApplicationListener 在此读取 application.yml"); System.out.println("5.5 应用 spring.main 配置到 SpringApplication\n"); System.out.println("关键: application.yml/properties 文件在此阶段加载!"); } }3.5 步骤6-7: 创建并准备上下文
/** * 创建应用上下文并准备 */ public class Step6_CreateAndPrepareContext { // 源码: SpringApplication.createApplicationContext() // // protected ConfigurableApplicationContext createApplicationContext() { // return this.applicationContextFactory.create(this.webApplicationType); // } // // 根据webApplicationType创建不同的上下文: // SERVLET -> AnnotationConfigServletWebServerApplicationContext // REACTIVE -> AnnotationConfigReactiveWebServerApplicationContext // NONE -> AnnotationConfigApplicationContext public static void main(String[] args) { System.out.println("=== 创建并准备上下文 ===\n"); System.out.println("步骤6: 创建ApplicationContext"); System.out.println(" 根据推断的类型创建对应的上下文实现\n"); System.out.println("步骤7: prepareContext - 准备上下文"); System.out.println(" 7.1 设置Environment"); System.out.println(" 7.2 后置处理(postProcessApplicationContext)"); System.out.println(" 7.3 执行ApplicationContextInitializer"); System.out.println(" 7.4 发布ApplicationContextInitializedEvent"); System.out.println(" 7.5 注册启动源(primarySources)"); System.out.println(" 7.6 发布ApplicationPreparedEvent"); } }3.6 步骤8: 刷新上下文(Spring核心启动)
/** * refreshContext: Spring Framework的核心启动流程 * * 这是整个启动过程中最关键、最复杂的步骤 */ public class Step8_RefreshContext { // 源码: SpringApplication.refreshContext() // -> AbstractApplicationContext.refresh() // // public void refresh() throws BeansException { // synchronized (this.startupShutdownMonitor) { // // 1. 准备刷新 // prepareRefresh(); // // // 2. 获取BeanFactory // ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // // // 3. 准备BeanFactory // prepareBeanFactory(beanFactory); // // // 4. BeanFactory后置处理 // postProcessBeanFactory(beanFactory); // // // 5. 执行BeanFactoryPostProcessor // invokeBeanFactoryPostProcessors(beanFactory); // // 这里会执行 ConfigurationClassPostProcessor // // 完成 @Configuration 类的解析和 @ComponentScan // // // 6. 注册BeanPostProcessor // registerBeanPostProcessors(beanFactory); // // // 7. 初始化MessageSource // initMessageSource(); // // // 8. 初始化事件广播器 // initApplicationEventMulticaster(); // // // 9. 子类扩展点(onRefresh) // onRefresh(); // // ServletWebServerApplicationContext 在这里启动内嵌Web服务器! // // // 10. 注册监听器 // registerListeners(); // // // 11. 实例化所有非懒加载的单例Bean // finishBeanFactoryInitialization(beanFactory); // // @Service、@Controller、@Repository 等Bean在这里创建 // // // 12. 完成刷新 // finishRefresh(); // } // } public static void main(String[] args) { System.out.println("=== refresh() 12个核心步骤 ===\n"); System.out.println("1. prepareRefresh()"); System.out.println(" - 设置启动时间、状态标记"); System.out.println(" - 验证必要属性\n"); System.out.println("2. obtainFreshBeanFactory()"); System.out.println(" - 获取BeanFactory(Spring容器)\n"); System.out.println("3. prepareBeanFactory()"); System.out.println(" - 设置类加载器、表达式解析器"); System.out.println(" - 注册默认BeanPostProcessor\n"); System.out.println("4. postProcessBeanFactory()"); System.out.println(" - 子类扩展点(Web上下文扫描特殊Bean)\n"); System.out.println("5. invokeBeanFactoryPostProcessors() ★★★"); System.out.println(" - 执行所有BeanFactoryPostProcessor"); System.out.println(" - ConfigurationClassPostProcessor 解析 @Configuration"); System.out.println(" - @ComponentScan 扫描Bean定义"); System.out.println(" - @EnableAutoConfiguration 加载自动配置"); System.out.println(" - 这是自动配置生效的关键步骤!\n"); System.out.println("6. registerBeanPostProcessors()"); System.out.println(" - 注册BeanPostProcessor到容器\n"); System.out.println("7-10. 初始化辅助组件"); System.out.println(" - MessageSource、事件广播器、Web服务器\n"); System.out.println("11. finishBeanFactoryInitialization() ★★★"); System.out.println(" - 实例化所有单例Bean"); System.out.println(" - 处理循环依赖(三级缓存)"); System.out.println(" - 这是最耗时的步骤!\n"); System.out.println("12. finishRefresh()"); System.out.println(" - 发布ContextRefreshedEvent"); } }3.7 步骤9: 启动内嵌Web服务器
/** * Web服务器启动细节 */ public class Step9_StartWebServer { // 源码: ServletWebServerApplicationContext.onRefresh() // -> createWebServer() // -> webServer.start() // // private void createWebServer() { // WebServer webServer = this.webServer; // ServletContext servletContext = getServletContext(); // if (webServer == null && servletContext == null) { // // 获取WebServerFactory(如TomcatServletWebServerFactory) // ServletWebServerFactory factory = getWebServerFactory(); // // // 创建Web服务器(内嵌Tomcat/Jetty/Undertow) // this.webServer = factory.getWebServer(getSelfInitializer()); // } // // 启动Web服务器 // initPropertySources(); // } public static void main(String[] args) { System.out.println("=== 启动内嵌Web服务器 ===\n"); System.out.println("触发时机: refresh() 中的 onRefresh() 步骤\n"); System.out.println("执行流程:"); System.out.println("1. 获取 ServletWebServerFactory Bean"); System.out.println(" - 根据类路径自动选择:"); System.out.println(" * Tomcat: spring-boot-starter-web 默认"); System.out.println(" * Jetty: 排除Tomcat,引入Jetty"); System.out.println(" * Undertow: 排除Tomcat,引入Undertow"); System.out.println("2. 创建 WebServer 实例"); System.out.println("3. 配置 Servlet、Filter、Listener"); System.out.println("4. 调用 webServer.start() 启动服务"); System.out.println("5. 发布 ServletWebServerInitializedEvent\n"); System.out.println("服务器启动后:"); System.out.println("- 端口已绑定"); System.out.println("- DispatcherServlet 已就绪"); System.out.println("- 可以接收HTTP请求"); } }3.8 步骤10-11: Runner与完成事件
/** * 启动的最后步骤: 执行Runner并发布完成事件 */ public class Step10_RunnersAndFinish { // 源码: SpringApplication.callRunners() // -> ApplicationRunner.run() 和 CommandLineRunner.run() public static void main(String[] args) { System.out.println("=== 执行Runner ===\n"); System.out.println("Runner执行顺序:"); System.out.println("1. ApplicationRunner (优先级高)"); System.out.println(" - 接收 ApplicationArguments (已解析的参数)"); System.out.println("2. CommandLineRunner (优先级低)"); System.out.println(" - 接收 String[] (原始参数)\n"); System.out.println("使用示例:"); System.out.println("@Component"); System.out.println("public class DataInitializer implements CommandLineRunner {"); System.out.println(" public void run(String... args) {"); System.out.println(" // 初始化数据、预热缓存"); System.out.println(" }"); System.out.println("}\n"); System.out.println("最后: 发布 ApplicationStartedEvent"); System.out.println(" 发布 ApplicationReadyEvent"); System.out.println(" Spring Boot启动完成!"); } }四、扩展点时机汇总
/** * Spring Boot启动过程的完整扩展点 */ public class ExtensionPointsSummary { public static void main(String[] args) { System.out.println("=== 启动过程扩展点执行顺序 ===\n"); String[] timeline = { "1. SpringApplicationRunListener.starting()", "2. ApplicationContextInitializer.initialize()", "3. SpringApplicationRunListener.environmentPrepared()", "4. SpringApplicationRunListener.contextPrepared()", "5. SpringApplicationRunListener.contextLoaded()", "", "=== refresh() 阶段 ===", "6. BeanFactoryPostProcessor.postProcessBeanFactory()", "7. @PostConstruct", "8. InitializingBean.afterPropertiesSet()", "9. BeanPostProcessor (贯穿Bean创建过程)", "", "=== refresh() 之后 ===", "10. SpringApplicationRunListener.started()", "11. ApplicationRunner.run()", "12. CommandLineRunner.run()", "13. SpringApplicationRunListener.ready()", }; for (String step : timeline) { System.out.println(step); } } }五、面试高频问题
5.1 启动过程核心面试题
/** * 面试高频问题与答案 */ public class InterviewQuestions { public static void main(String[] args) { System.out.println("=== 面试高频问题 ===\n"); // Q1 System.out.println("Q1: Spring Boot启动过程?"); System.out.println("A: 两大阶段11步:"); System.out.println(" 构造阶段: 推断类型、加载初始化器/监听器、推断主类"); System.out.println(" 运行阶段: 准备环境、创建上下文、准备上下文、"); System.out.println(" 刷新上下文(Spring核心)、启动Web服务器、"); System.out.println(" 执行Runner、发布完成事件\n"); // Q2 System.out.println("Q2: 自动配置什么时候生效?"); System.out.println("A: refresh()的invokeBeanFactoryPostProcessors()步骤"); System.out.println(" ConfigurationClassPostProcessor 解析 @EnableAutoConfiguration"); System.out.println(" -> AutoConfigurationImportSelector 加载 spring.factories"); System.out.println(" -> 条件过滤后注册自动配置类的Bean定义\n"); // Q3 System.out.println("Q3: Web服务器什么时候启动?"); System.out.println("A: refresh()的onRefresh()步骤"); System.out.println(" ServletWebServerApplicationContext 会在此创建并启动"); System.out.println(" 内嵌Tomcat/Jetty/Undertow\n"); // Q4 System.out.println("Q4: application.yml什么时候加载?"); System.out.println("A: 准备环境阶段(步骤5)"); System.out.println(" ConfigFileApplicationListener 监听到环境准备事件"); System.out.println(" 读取 application.yml/properties 并添加到Environment"); } }六、总结
6.1 启动过程核心步骤速查
| 步骤 | 做什么 | 关键点 |
|------|--------|--------|
| 推断类型 | 检查类路径 | 决定Context和WebServer类型 |
| 加载SPI组件 | 读spring.factories | 初始化器和监听器 |
| 准备环境 | 创建Environment | 加载application.yml |
| 创建上下文 | 根据类型new | 三种Context实现 |
| 准备上下文 | 设置属性 | 执行初始化器 |
|刷新上下文|refresh()|Bean扫描、自动配置、单例实例化|
| 启动WebServer | onRefresh() | 内嵌Tomcat启动 |
| 执行Runner | callRunners() | CommandLineRunner |
6.2 关键类关系图
SpringApplication ├── 创建时: 加载Initializer和Listener └── run()时: ├── 创建Environment ├── 创建ApplicationContext │ └── refresh() │ ├── BeanFactoryPostProcessor (自动配置生效) │ ├── onRefresh() (WebServer启动) │ └── finishBeanFactoryInitialization() (Bean实例化) └── 发布Ready事件---
如果本文帮你理解了Spring Boot启动的全过程,欢迎点赞收藏。有任何疑问,欢迎评论区交流!
