文章
SpringBoot的启动流程
Spring Boot 在启动时主要做了以下几大类事情: 1. 环境准备 2. 核心容器构建 3. Bean 初始化 4. Web 服务器启动 5. Runner 执行
目录
- Spring Boot 启动的入口
- Spring Boot 启动流程详解
- 1. 创建 SpringApplication 实例
- **2. 运行 **SpringApplication
- 2.1. 执行 SpringApplicationRunListeners (启动前)
- 2.2. 准备 ApplicationContext (核心)
- 2.3. 刷新 ApplicationContext (Bean 生命周期开始)
- 2.4. 执行 SpringApplicationRunListeners (刷新后)
- **2.5. 调用 CommandLineRunner / **ApplicationRunner
- 2.6. 执行 SpringApplicationRunListeners (运行中)
- 3. 启动 Web 服务器 (如果存在)
- 4. 应用就绪
- 总结 Spring Boot 启动时做的事情
我们来详细解析一下 Spring Boot 的启动流程以及在这个过程中它都做了哪些事情。理解这个流程是深入掌握 Spring Boot 的关键。
Spring Boot 启动的入口#
Spring Boot 应用的启动通常从一个带有 @SpringBootApplication 注解的 main 方法开始。
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
所有的魔法都始于 SpringApplication.run() 方法。
Spring Boot 启动流程详解#
SpringApplication.run() 方法的执行可以概括为以下几个主要阶段:
Rendering diagram...
1. 创建 SpringApplication 实例#
- 推断应用类型: Spring Boot 首先会尝试推断应用程序的类型,是传统的
Servlet应用(如 Spring MVC)、响应式WebFlux应用,还是非 Web 应用。这会影响后续自动配置的决策。 - 加载
ApplicationContextInitializer和 ****ApplicationListener: Spring Boot 会从META-INF/spring.factories文件中查找并加载所有ApplicationContextInitializer和ApplicationListener的实现类。这些是容器启动前和启动过程中可以执行自定义逻辑的扩展点。 - 推断主应用类: 确定启动类(通常是调用
main方法的类)。
**2. 运行 **SpringApplication#
这是 run() 方法的核心阶段,它会执行以下步骤:
2.1. 执行 SpringApplicationRunListeners (启动前)#
SpringApplicationRunListeners也是从META-INF/spring.factories加载的。starting(): 这是容器启动的第一个事件,表示SpringApplication开始运行。environmentPrepared(): 环境(Environment,包括配置属性、profiles 等)已经准备好,但ApplicationContext尚未创建。在这个阶段,可以修改环境属性。contextPrepared():ApplicationContext已经创建(但尚未刷新),Bean Definition已经加载完成,但 Bean 实例尚未创建。contextLoaded():ApplicationContext已经加载完成,所有的 Bean 定义都已经注册到BeanFactory,但 Bean 实例还未完全初始化。
2.2. 准备 ApplicationContext (核心)#
这是 Spring 容器真正开始构建的阶段。
- 创建 ****
ConfigurableApplicationContext: 根据推断的应用类型,创建一个适当的ApplicationContext实例。- 对于 Web 应用,通常是
AnnotationConfigServletWebServerApplicationContext(嵌入式 Servlet 容器) 或AnnotationConfigReactiveWebServerApplicationContext(WebFlux)。 - 对于非 Web 应用,是
AnnotationConfigApplicationContext。
- 对于 Web 应用,通常是
- 应用 ****
ApplicationContextInitializer: 调用在第一步加载的所有ApplicationContextInitializer的initialize()方法。这允许在ApplicationContext刷新之前对其进行编程性修改。 - 注册主应用类为 Bean: 将
@SpringBootApplication所在的类注册为一个 Bean 定义。 - 注册自动配置类 (Auto-configurations):
- 核心步骤: Spring Boot 会查找所有
META-INF/spring.factories中org.springframework.boot.autoconfigure.EnableAutoConfiguration键指定的自动配置类。 - 条件评估: 对于每个自动配置类,会根据
@ConditionalOnClass、@ConditionalOnMissingBean等条件注解进行评估。只有满足条件的自动配置类才会被启用,并将其内部定义的 Bean 注册到ApplicationContext。 - 这正是“开箱即用”魔法发生的地方!例如,如果检测到
spring-boot-starter-web依赖,就会自动配置DispatcherServlet、EmbeddedWebServerFactory(如 Tomcat),如果检测到数据库驱动和相关属性,就会自动配置DataSource等。
- 核心步骤: Spring Boot 会查找所有
- 注册其他 Bean 定义:
@ComponentScan: 扫描@SpringBootApplication所在的包及其子包,发现所有带有@Component、@Service、@Repository、@Controller、@Configuration等注解的类,并将其注册为 Bean 定义。@Bean** 方法**: 扫描所有@Configuration类中带有@Bean注解的方法,将它们返回的对象注册为 Bean 定义。
2.3. 刷新 ApplicationContext (Bean 生命周期开始)#
这是 Spring 容器生命周期中最关键的阶段,所有的 Bean 实例化和初始化都发生在这里。
- BeanPostProcessor 注册: 注册所有
BeanPostProcessor实例。 - 国际化、事件发布器等准备: 准备
MessageSource、ApplicationEventPublisher等基础设施。 - 实例化单例 Bean: 这是 Bean 生命周期中,Bean 实例被创建和初始化的大部分工作发生的地方。 默认情况下,所有非懒加载的单例 Bean 在此阶段被实例化、属性填充、执行初始化回调(
@PostConstruct,InitializingBean,init-method),并经过BeanPostProcessor的前置和后置处理。 - Spring AOP: 如果应用了 Spring AOP,AOP 代理通常会在 Bean 的
postProcessAfterInitialization()阶段被创建,并替换原始 Bean。
2.4. 执行 SpringApplicationRunListeners (刷新后)#
started():ApplicationContext已经刷新完成,所有 Bean 已经完全初始化并可供使用。
**2.5. 调用 CommandLineRunner / **ApplicationRunner#
- 执行 Runners: Spring Boot 会查找并执行所有实现了
CommandLineRunner或ApplicationRunner接口的 Bean。这些接口提供了在应用启动后执行特定代码的机制,通常用于执行一些初始化数据、启动后台任务等。
2.6. 执行 SpringApplicationRunListeners (运行中)#
running(): 应用程序已经完全启动并开始运行。
3. 启动 Web 服务器 (如果存在)#
- 如果应用类型是 Web 应用(Servlet 或 WebFlux),在
ApplicationContext刷新完成后,会启动嵌入式 Web 服务器(Tomcat, Jetty 或 Undertow)。 DispatcherServlet(对于 Spring MVC)或相应的 WebFlux 处理器会被注册到 Web 服务器中,并开始监听传入的 HTTP 请求。
4. 应用就绪#
- 至此,Spring Boot 应用程序已经完全启动,Web 服务器正在监听端口,可以处理客户端请求了。
总结 Spring Boot 启动时做的事情#
从上述流程中可以看出,Spring Boot 在启动时主要做了以下几大类事情:
- 环境准备: 推断应用类型、加载配置属性、初始化日志系统等。
- 核心容器构建:
- 创建
ApplicationContext。 - 自动配置: 根据 classpath 和条件注解,智能地自动配置各种基础设施 Bean(如数据源、Web 服务器、MVC 组件、JPA/Hibernate 配置等)。这是 Spring Boot 最显著的特性。
- 组件扫描: 扫描并注册开发者定义的 Bean(通过
@Component、@Service、@Controller、@Repository、@Configuration和@Bean方法)。
- 创建
- Bean 初始化: 实例化所有单例 Bean,进行依赖注入,并执行所有初始化回调方法。AOP 代理也在这个阶段创建。
- Web 服务器启动: 如果是 Web 应用,启动内嵌的 Web 服务器,并注册
DispatcherServlet等处理程序。 - Runner 执行: 运行
CommandLineRunner和ApplicationRunner,允许开发者在应用完全启动后执行自定义逻辑。 通过这一系列自动化的、按条件进行的步骤,Spring Boot 极大地简化了 Spring 应用程序的配置和启动过程,让开发者能够更专注于业务逻辑的实现。