Spring Boot 启动流程深度解析
一、启动入口与核心对象
1.1 启动入口
Spring Boot 应用通过带有 @SpringBootApplication 注解的主类启动,其 main 方法调用 SpringApplication.run() 触发完整启动流程:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args); //
}
}
1.2 SpringApplication 构造
创建 SpringApplication 实例时完成关键初始化:
- 推断应用类型:通过类路径判断是 Web/Servlet/Reactive 应用
- 加载初始化器:从
META-INF/spring.factories加载ApplicationContextInitializer - 注册监听器:收集
ApplicationListener实现类 - 确定主应用类:通过堆栈跟踪定位启动类
// SpringApplication 构造方法关键逻辑
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners(getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass(); //
}
二、启动核心流程
2.1 环境准备阶段
关键操作:
- 创建 ConfigurableEnvironment:封装系统属性和环境变量
- 加载配置文件:解析
application.properties/yml和命令行参数 - 绑定配置属性:将配置值注入
Environment对象
protected ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments args) {
ConfigurableEnvironment env = getOrCreateEnvironment();
configureEnvironment(env, args.getSourceArgs()); //
listeners.environmentPrepared(env); // 触发环境准备完成事件
return env;
}
2.2 应用上下文创建
上下文类型选择:
| 应用类型 | 上下文实现类 | 特点 |
|---|---|---|
| Web 应用 | AnnotationConfigServletWebServerApplicationContext | 集成 Servlet 容器 |
| 非 Web 应用 | AnnotationConfigApplicationContext | 纯 Java 应用 |
protected ConfigurableApplicationContext createApplicationContext() {
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(
this.applicationContextClass); //
}
2.3 上下文刷新阶段
核心方法链:
refreshContext(context);
↓
refresh(context); // 调用 AbstractApplicationContext.refresh()
↓
invokeBeanFactoryPostProcessors(beanFactory); // 执行 BeanFactoryPostProcessor
↓
registerBeanPostProcessors(beanFactory); // 注册 BeanPostProcessor
↓
finishRefresh(); // 发布 ContextRefreshedEvent
关键扩展点:
- BeanFactoryPostProcessor:修改 Bean 定义(如
PropertySourcesPlaceholderConfigurer) - BeanPostProcessor:增强 Bean 实例(如
@PostConstruct处理)
2.4 自动配置触发
通过 @EnableAutoConfiguration 注解触发,核心逻辑:
- 加载自动配置类:读取
spring.factories中的AutoConfiguration - 条件筛选:基于
@Conditional系列注解过滤配置类 - 注册 Bean:将符合条件的配置类注册到容器
// AutoConfigurationImportSelector 核心逻辑
protected List<String> getCandidateConfigurations(
AnnotationMetadata metadata,
AnnotationAttributes attributes) {
return SpringFactoriesLoader.loadFactoryNames(
getAnnotationClass(attributes),
getBeanClassLoader()); //
}
2.5 内嵌服务器启动
Web 应用特有的初始化流程:
- 创建 ServletWebServerApplicationContext
- 初始化 Servlet 容器工厂(Tomcat/Jetty/Undertow)
- 启动容器:绑定端口并发布应用
// ServletWebServerApplicationContext 刷新逻辑
protected void createWebServer() {
WebServer webServer = this.webServerFactory.getWebServer(
new ServletContextInitializer[] { this.servletContextInitializer });
webServer.start(); //
}
三、启动后处理
3.1 执行 Runner 接口
callRunners(context, applicationArguments); //
↓
List<ApplicationRunner> runners = getBeansOfType(ApplicationRunner.class);
for (ApplicationRunner runner : runners) {
runner.run(args); // 执行自定义启动逻辑
}
3.2 发布就绪事件
listeners.started(context); // 触发 ApplicationStartedEvent
listeners.running(context); // 触发 ApplicationReadyEvent
四、关键源码验证
4.1 启动耗时统计
通过 StopWatch 记录各阶段耗时:
StopWatch stopWatch = new StopWatch();
stopWatch.start("Spring Boot 初始化");
// ... 各阶段操作
stopWatch.stop();
logger.info("启动耗时: {} ms", stopWatch.getTotalTimeMillis()); //
4.2 启动监听器示例
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// 应用完全启动后执行
}
}
五、性能优化建议
5.1 配置调优
# 减少日志输出
spring.main.log-startup-info=false
# 禁用Banner
spring.main.banner-mode=off
# 延迟Bean初始化
spring.main.lazy-initialization=true
5.2 启动加速方案
- 并行初始化 Bean:通过
@Order控制加载顺序 - 条件化自动配置:避免加载无用组件
- 使用 Spring Native:AOT 编译减少反射开销
六、扩展点全景图
graph TD
A[SpringApplication.run] --> B[创建上下文]
B --> C[准备环境]
C --> D[加载配置]
D --> E[创建BeanFactory]
E --> F[注册BeanDefinition]
F --> G[Bean实例化]
G --> H[依赖注入]
H --> I[执行BeanPostProcessor]
I --> J[发布应用就绪事件]
通过深入理解该流程,我们可精准定位启动性能瓶颈,实现:
- 启动时间优化 40%-70%
- 内存占用减少 30%
- 更好的分布式系统集成