Spring Boot 启动加载执行链路分析
看源码太枯燥,我们学思维就好;细节不深究,框架只要搭起来,剩下的就是按部就班的填空了。
一、核心启动流程概览
二、详细执行链路分析
1. 入口:main()
方法
码友们肯定都知道,SpringBoot的启动,只需要依赖web,然后再写以一个如下的main启动方法,就可以搭建起一个web服务了。
聪明的码友如果想知道:在main运行的那一刻,SpringBoot框架到底做了哪些事情?可以看看SpringBoot 启动入口深度解析:main方法执行全流程
@SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args); // 启动入口}
}
主类上需要添加@SpringBootApplication,不加就会报错
2. SpringApplication
初始化
// SpringApplication 构造方法核心逻辑
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));this.webApplicationType = WebApplicationType.deduceFromClasspath();// 推断应用类型// 加载扩展点this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 加载Listenerthis.mainApplicationClass = deduceMainApplicationClass();
}
关键步骤:
- 推断应用类型:检查类路径(Servlet/Reactive/None)
- 加载
spring.factories
:从META-INF/spring.factories
加载扩展点 - 初始化引导注册器:Spring Boot 3.0+ 新增
BootstrapRegistry
机制
3. 环境准备(Environment
)
// SpringApplication.run() → prepareEnvironment()
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {// 1. 创建环境实例ConfigurableEnvironment environment = getOrCreateEnvironment();// 2. 配置环境(命令行参数、Profile 等)configureEnvironment(environment, applicationArguments.getSourceArgs());// 3. 附加配置属性源(支持 Spring Boot 配置绑定)ConfigurationPropertySources.attach(environment);// 4. 发布 "环境准备完成" 事件(允许监听器修改环境)listeners.environmentPrepared(bootstrapContext, environment);// 5. 调整默认属性源位置(确保优先级正确)DefaultPropertiesPropertySource.moveToEnd(environment);// 6. 校验环境前缀属性(防止非法配置)Assert.state(!environment.containsProperty("spring.main.environment-prefix"),"Environment prefix cannot be set via properties.");// 7. 将环境属性绑定到 SpringApplication 对象bindToSpringApplication(environment);// 8. 环境类型转换(非自定义环境时)if (!this.isCustomEnvironment) {EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}// 9. 重新附加配置属性源(确保转换后属性源正确)ConfigurationPropertySources.attach(environment);return environment;
}
执行顺序:
- 根据应用类型(Servlet/Reactive/None)创建对应的环境对象;如
StandardServletEnvironment
(Web应用) - 加载配置源(
application.properties
/application.yml
)(–spring.profiles.active 参数) - 发布
ApplicationEnvironmentPreparedEvent
- 触发
ConfigFileApplicationListener
加载配置文件 - 触发
LoggingApplicationListener
初始化日志系统
- 触发
4. 创建应用上下文(ApplicationContext
)
// SpringApplication.run() → createApplicationContext()
protected ConfigurableApplicationContext createApplicationContext() {return this.applicationContextFactory.create(this.webApplicationType);
}
// 默认创建 AnnotationConfigServletWebServerApplicationContext(Web应用)
创建的应用上下文类型:
应用类型 | 上下文实现类 | 说明 |
---|---|---|
SERVLET | AnnotationConfigServletWebServerApplicationContext | 支持 Servlet Web 应用(Tomcat/Jetty),整合了 Web 服务器启动 |
REACTIVE | AnnotationConfigReactiveWebServerApplicationContext | 支持响应式 Web 应用(Netty/WebFlux),内置响应式服务器启动 |
NONE | AnnotationConfigApplicationContext | 标准非 Web 应用上下文,仅处理 Spring Bean 容器 |
applicationContextFactory
的来源- 默认使用
ApplicationContextFactory.DEFAULT
实现 - 可通过
SpringApplication.setApplicationContextFactory()
自定义
- 默认使用
webApplicationType
的确定
在SpringApplication
构造阶段通过以下方式确定:
this.webApplicationType = WebApplicationType.deduceFromClasspath();
根据类路径推断应用类型:
-
存在
DispatcherHandler
→REACTIVE
-
存在
Servlet
或ConfigurableWebApplicationContext
→SERVLET
-
其他 →
NONE
(普通 Java 应用)
- 工厂创建逻辑 (
ApplicationContextFactory.create()
)
5. 准备上下文(prepareContext()
)
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// 1. 设置环境到上下文context.setEnvironment(environment);// 2. 后处理应用上下文postProcessApplicationContext(context);// 3. 处理AOT生成的初始化器addAotGeneratedInitializerIfNecessary(this.initializers);// 4. 应用初始化器applyInitializers(context);// 5. 发布ContextPrepared事件listeners.contextPrepared(context);// 6. 关闭引导上下文并注册bootstrapContext.close(context);// 7. 记录启动信息if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// 8. 注册关键单例BeanConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}// 9. 配置BeanFactory策略if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {// 设置循环引用策略autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {// 设置Bean定义覆盖策略listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}}// 10. 处理延迟初始化if (this.lazyInitialization) {context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}// 11. 添加属性源排序处理器context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));// 12. 加载主配置源if (!AotDetector.useGeneratedArtifacts()) {Set<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");load(context, sources.toArray(new Object[0]));}// 13. 发布ContextLoaded事件listeners.contextLoaded(context);
}
核心步骤:
- 上下文基础配置
- 设置环境对象(
context.setEnvironment(environment)
) - 执行上下文后处理(
postProcessApplicationContext
),如添加资源加载器 - 应用所有初始化器(
applyInitializers
),执行自定义初始化逻辑
- 设置环境对象(
- 事件通知与引导关闭
- 发布
ContextPreparedEvent
事件(listeners.contextPrepared
) - 关闭引导上下文(
bootstrapContext.close
),将引导阶段单例Bean迁移至主上下文
- 发布
- 关键Bean注册
- 注册启动参数Bean(
springApplicationArguments
) - 注册Banner打印对象(
springBootBanner
) - 配置BeanFactory策略(循环引用/Bean覆盖等)
- 注册启动参数Bean(
- 特殊处理
- 添加懒加载处理器(若启用全局懒加载)
- 添加属性源排序处理器(确保配置优先级)
- 加载主配置源(
getAllSources()
+load()
)
- 最终事件通知
- 发布
ContextLoadedEvent
事件(listeners.contextLoaded
),允许最终调整上下文
- 发布
6. 刷新上下文(refreshContext()
→ 核心!)
// AbstractApplicationContext.refresh()
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 阶段0: 刷新准备StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");this.prepareRefresh(); // 准备刷新上下文// 阶段1: 获取新BeanFactoryConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// 阶段2: 配置BeanFactorythis.prepareBeanFactory(beanFactory);try {// 阶段3: 后处理BeanFactorythis.postProcessBeanFactory(beanFactory);// 阶段4: 执行BeanFactory后处理器StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");this.invokeBeanFactoryPostProcessors(beanFactory); // 关键:加载配置类/配置属性this.registerBeanPostProcessors(beanFactory); // 注册Bean后处理器beanPostProcess.end();// 阶段5: 初始化消息源this.initMessageSource();// 阶段6: 初始化事件广播器this.initApplicationEventMulticaster();// 阶段7: 扩展点:子类初始化特殊Beanthis.onRefresh(); // Spring Boot 在此启动Web服务器// 阶段8: 注册监听器this.registerListeners();// 阶段9: 完成BeanFactory初始化this.finishBeanFactoryInitialization(beanFactory); // 实例化所有非懒加载单例// 阶段10: 完成刷新this.finishRefresh(); // 发布ContextRefreshedEvent事件} catch (BeansException ex) {// 异常处理:销毁已创建Bean并取消刷新this.destroyBeans();this.cancelRefresh(ex);throw ex;} finally {// 清理缓存this.resetCommonCaches();contextRefresh.end();}}
}
关键扩展点详解:
1. invokeBeanFactoryPostProcessors()
- 自动配置入口
this.invokeBeanFactoryPostProcessors(beanFactory);
扩展机制:
- 执行
ConfigurationClassPostProcessor
处理@Configuration
类 - Spring Boot 关键:触发
AutoConfigurationImportSelector
- 扫描
META-INF/spring.factories
加载自动配置类 - 执行条件注解过滤 (
@ConditionalOnClass
等) - 加载顺序控制:
@AutoConfigureOrder
,@AutoConfigureBefore/After
- 扫描
典型流程:
2. onRefresh()
- 内嵌服务器启动
protected void onRefresh() {super.onRefresh();createWebServer(); // Spring Boot 扩展
}
扩展实现:
ServletWebServerApplicationContext
中:
protected void onRefresh() {super.onRefresh();try {createWebServer(); // 创建并启动Tomcat/Jetty/Undertow} catch (Throwable ex) {...}
}
核心动作:
- 从
BeanFactory
获取ServletWebServerFactory
- 使用
factory.getWebServer()
创建服务器实例 - 绑定
server.port
等配置属性 - 注册
DispatcherServlet
(Servlet 环境) 或WebHandler
(响应式环境)
3. finishBeanFactoryInitialization()
- 单例初始化扩展
finishBeanFactoryInitialization(beanFactory);
Spring Boot 扩展点:
- 健康检查系统:
HealthEndpointAutoConfiguration
- **注册 **
HealthContributorRegistry
- 内置磁盘/数据源/JMS 等健康指示器
- **注册 **
- 配置属性绑定:
ConfigurationPropertiesBindingPostProcessor
- **处理 **
@ConfigurationProperties
注解 - 将环境属性绑定到 Bean 字段
- **处理 **
- 启动指标:
ApplicationStartup
实现- 记录 Bean 初始化耗时
- **跟踪 **
@Bean
方法执行
4. finishRefresh()
- 生命周期回调
protected void finishRefresh() {// 1. 发布ContextRefreshedEventpublishEvent(new ContextRefreshedEvent(this));// 2. Spring Boot扩展:启动完成处理LiveBeansView.registerApplicationContext(this);
}
7. 刷新后处理
// 扩展点
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
执行顺序:
- 发布
ApplicationStartedEvent
- 执行
ApplicationRunner
和CommandLineRunner
- 按
@Order
顺序执行
- 按
- 发布
ApplicationReadyEvent
三、Spring框架集成关键点
- 自动配置原理:
- 条件注解:
@ConditionalOnClass
、@ConditionalOnMissingBean
- 配置类:
spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 条件注解:
- Servlet容器启动:
ServletWebServerFactoryAutoConfiguration
→ 创建TomcatServletWebServerFactory
DispatcherServletAutoConfiguration
→ 注册DispatcherServlet
- 数据源与事务:
DataSourceAutoConfiguration
→ 创建DataSource
TransactionAutoConfiguration
→ 启用@Transactional
四、思维导图总结
版本说明:
- Spring Boot 3.5.0 使用 Spring 6.2.7
- 自动配置路径:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 事件驱动模型:
ApplicationEvent
+ApplicationListener