1. Spring Boot 3.x启动流程全景解析
作为一名长期深耕Java生态的开发者,我见证了Spring Boot从1.x到3.x的完整演进历程。Spring Boot 3.x的启动流程在保持"约定优于配置"核心理念的同时,通过模块化重构和性能优化,实现了启动速度提升和内存占用的显著降低。本文将基于最新3.x版本源码,深入剖析启动流程的每个关键环节。
1.1 新版启动流程的核心变化
Spring Boot 3.x在启动机制上做了几项重要改进:
- BootstrapRegistry初始化器:新增的扩展点,允许在应用上下文创建前注册组件
- 自动配置加载机制:从传统的
spring.factories迁移到META-INF/spring/目录下的新格式 - GraalVM原生支持:为AOT编译提供基础设施,使应用能编译为原生可执行文件
- Jakarta EE 9+适配:所有javax包名统一迁移到jakarta命名空间
这些变化不仅影响框架本身,也改变了我们扩展Spring Boot的方式。下面通过一个典型启动示例开始我们的探索:
java复制@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
// 新版run方法返回GenericApplicationContext而非ConfigurableApplicationContext
var context = SpringApplication.run(MyApp.class, args);
}
}
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 启动入口:SpringApplication的构造与初始化
2.1 静态工厂方法背后的设计哲学
SpringApplication.run()看似简单,实则隐藏着精妙的设计:
java复制public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
long startTime = System.currentTimeMillis();
// 构造与执行分离的设计
SpringApplication application = new SpringApplication(primarySources);
return application.run(args);
}
这种构造与执行分离的设计带来了两个关键优势:
- 允许在调用run()前进行自定义配置(如关闭Banner、设置额外配置源)
- 为响应式编程模型提供了统一入口
2.2 构造阶段的资源加载
SpringApplication的构造函数完成了启动前的关键准备工作:
java复制public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 1. 推断应用类型(重要!决定后续创建哪种ApplicationContext)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 2. 加载BootstrapRegistryInitializer(3.x新增)
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
// 3. 加载ApplicationContextInitializer
setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 4. 加载ApplicationListener
setListeners(getSpringFactoriesInstances(ApplicationListener.class));
// 5. 推断主类(用于日志和异常堆栈显示
