返回文章列表

文章

SpringBoot的启动流程

Spring Boot 在启动时主要做了以下几大类事情: 1. 环境准备 2. 核心容器构建 3. Bean 初始化 4. Web 服务器启动 5. Runner 执行

目录
  1. Spring Boot 启动的入口
  2. Spring Boot 启动流程详解
  3. 1. 创建 SpringApplication 实例
  4. **2. 运行 **SpringApplication
  5. 2.1. 执行 SpringApplicationRunListeners (启动前)
  6. 2.2. 准备 ApplicationContext (核心)
  7. 2.3. 刷新 ApplicationContext (Bean 生命周期开始)
  8. 2.4. 执行 SpringApplicationRunListeners (刷新后)
  9. **2.5. 调用 CommandLineRunner / **ApplicationRunner
  10. 2.6. 执行 SpringApplicationRunListeners (运行中)
  11. 3. 启动 Web 服务器 (如果存在)
  12. 4. 应用就绪
  13. 总结 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 文件中查找并加载所有 ApplicationContextInitializerApplicationListener 的实现类。这些是容器启动前和启动过程中可以执行自定义逻辑的扩展点。
  • 推断主应用类: 确定启动类(通常是调用 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
  • 应用 ****ApplicationContextInitializer: 调用在第一步加载的所有 ApplicationContextInitializerinitialize() 方法。这允许在 ApplicationContext 刷新之前对其进行编程性修改。
  • 注册主应用类为 Bean: 将 @SpringBootApplication 所在的类注册为一个 Bean 定义。
  • 注册自动配置类 (Auto-configurations):
    • 核心步骤: Spring Boot 会查找所有 META-INF/spring.factoriesorg.springframework.boot.autoconfigure.EnableAutoConfiguration 键指定的自动配置类。
    • 条件评估: 对于每个自动配置类,会根据 @ConditionalOnClass@ConditionalOnMissingBean 等条件注解进行评估。只有满足条件的自动配置类才会被启用,并将其内部定义的 Bean 注册到 ApplicationContext
    • 这正是“开箱即用”魔法发生的地方!例如,如果检测到 spring-boot-starter-web 依赖,就会自动配置 DispatcherServletEmbeddedWebServerFactory(如 Tomcat),如果检测到数据库驱动和相关属性,就会自动配置 DataSource 等。
  • 注册其他 Bean 定义:
    • @ComponentScan: 扫描 @SpringBootApplication 所在的包及其子包,发现所有带有 @Component@Service@Repository@Controller@Configuration 等注解的类,并将其注册为 Bean 定义。
    • @Bean** 方法**: 扫描所有 @Configuration 类中带有 @Bean 注解的方法,将它们返回的对象注册为 Bean 定义。

2.3. 刷新 ApplicationContext (Bean 生命周期开始)#

这是 Spring 容器生命周期中最关键的阶段,所有的 Bean 实例化和初始化都发生在这里。

  • BeanPostProcessor 注册: 注册所有 BeanPostProcessor 实例。
  • 国际化、事件发布器等准备: 准备 MessageSourceApplicationEventPublisher 等基础设施。
  • 实例化单例 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 会查找并执行所有实现了 CommandLineRunnerApplicationRunner 接口的 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 在启动时主要做了以下几大类事情:

  1. 环境准备: 推断应用类型、加载配置属性、初始化日志系统等。
  2. 核心容器构建:
    • 创建 ApplicationContext
    • 自动配置: 根据 classpath 和条件注解,智能地自动配置各种基础设施 Bean(如数据源、Web 服务器、MVC 组件、JPA/Hibernate 配置等)。这是 Spring Boot 最显著的特性。
    • 组件扫描: 扫描并注册开发者定义的 Bean(通过 @Component@Service@Controller@Repository@Configuration@Bean 方法)。
  3. Bean 初始化: 实例化所有单例 Bean,进行依赖注入,并执行所有初始化回调方法。AOP 代理也在这个阶段创建。
  4. Web 服务器启动: 如果是 Web 应用,启动内嵌的 Web 服务器,并注册 DispatcherServlet 等处理程序。
  5. Runner 执行: 运行 CommandLineRunnerApplicationRunner,允许开发者在应用完全启动后执行自定义逻辑。 通过这一系列自动化的、按条件进行的步骤,Spring Boot 极大地简化了 Spring 应用程序的配置和启动过程,让开发者能够更专注于业务逻辑的实现。