Java面试题 — 说说Springboot 的启动流程?
Spring Boot 的启动流程是其简化开发的核心机制之一。本文将以 2.7.6 版本为例,详细剖析其启动流程的核心步骤与底层实现。
一、核心启动流程
1. 启动 Main 方法
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
通过组合注解 @SpringBootApplication 标记主类,其内部包含三个核心注解:
@SpringBootConfiguration:声明为配置类@EnableAutoConfiguration:激活自动配置@ComponentScan:开启组件扫描
2. 创建 SpringApplication 实例
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 推断应用类型(Servlet/Reactive/None)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 加载初始化器和监听器(通过META-INF/spring.factories)
setInitializers(loadFactoryNames(ApplicationContextInitializer.class));
setListeners(loadFactoryNames(ApplicationListener.class));
// 确定主应用类
this.mainApplicationClass = deduceMainApplicationClass();
}
3. 环境准备(ConfigurableEnvironment)
- 加载
application.properties/application.yml - 解析命令行参数
--server.port=8080 - 处理系统环境变量
- 激活 Profile:
spring.profiles.active=dev
4. 创建并刷新 ApplicationContext
// 根据应用类型创建上下文
context = createApplicationContext();
// 关键刷新操作
refreshContext(context);
刷新流程包含:
- 加载配置类(用户定义 + 自动配置)
- 注册 BeanDefinition
- 执行 BeanPostProcessor
- 初始化单例 Bean
- 启动嵌入式 Web 服务器
5. 启动嵌入式 Web 服务器
// 在WebServerApplicationContext中
this.webServer = factory.getWebServer(getServletContext());
this.webServer.start();
自动检测并启动 Tomcat/Jetty/Undertow,默认端口 8080。
6. 事件驱动机制
| 事件类型 | 触发时机 |
|---|---|
| ApplicationStartingEvent | 启动开始时 |
| ApplicationEnvironmentPrepared | 环境准备完成后 |
| ApplicationPreparedEvent | 上下文创建但未刷新时 |
| ApplicationStartedEvent | 上下文刷新后,runner执行前 |
| ApplicationReadyEvent | 所有启动逻辑完成后 |
7. 执行初始化逻辑
// 优先级:ApplicationRunner > CommandLineRunner
@Component
public class DemoRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
System.out.println("执行初始化任务...");
}
}
二、关键技术实现
1. 自动配置原理
通过 @Conditional 系列注解实现条件装配:
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
public class ServletWebServerFactoryAutoConfiguration {
// 自动配置Tomcat
}
2. 嵌入式服务器启动时序
ServletWebServerApplicationContext初始化- 通过
ServletWebServerFactory创建服务器实例 - 注册
DispatcherServlet并绑定到上下文路径 - 启动线程监听端口
3. Bean 生命周期管理
graph TD
A[BeanDefinition加载] --> B[实例化]
B --> C[属性注入]
C --> D[初始化前处理]
D --> E[@PostConstruct]
E --> F[初始化后处理]
三、性能优化建议
- 延迟初始化:
spring.main.lazy-initialization=true - 排除不必要的自动配置:
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) - 精简依赖:避免引入不需要的 starter
- 日志级别控制:启动阶段设置关键组件日志级别为 WARN
四、典型问题排查
1. 端口冲突
# 快速定位占用端口
$ netstat -ano | findstr :8080
2. 配置加载顺序
按优先级从高到低:
- 命令行参数
- JNDI 属性
- 系统环境变量
- application-{profile}.properties
- application.properties
3. Bean 循环依赖
- 使用
@Lazy延迟加载 - 重构代码解耦依赖
- Spring Boot 2.6+ 默认禁止循环依赖
通过理解 Spring Boot 的启动机制,开发者可以更好地进行性能调优、问题排查和定制化开发。这种"约定优于配置"的设计思想,使得开发者能够专注于业务逻辑而非框架配置。

708

被折叠的 条评论
为什么被折叠?



