Spring Boot 的自动装配原理:@EnableAutoConfiguration/AutoConfigurationImportSelector/条件

160 阅读3分钟

Spring Boot 启动过程详细分析

Spring Boot 的启动过程是面试中常见的重点问题,其背后涉及多个核心组件的协作。本文将深入剖析 Spring Boot 的启动细节,逐一说明每个步骤由哪个组件调用了什么功能,并提供请求链路图以直观展示整个流程。

启动入口:SpringApplication.run()

Spring Boot 应用的启动从 SpringApplication.run() 开始。这是开发者最熟悉的代码入口。

  • 组件org.springframework.boot.SpringApplication
  • 功能run(String... args) 方法是静态方法,接收命令行参数并启动应用。
  • 细节
    1. 创建 SpringApplication 实例。
    2. 调用实例方法 run(args) 执行启动逻辑。

代码示例:

public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
}

第一步:SpringApplication 实例化

  • 组件org.springframework.boot.SpringApplication
  • 功能:构造函数 SpringApplication(ResourceLoader, Class<?>...)
  • 细节
    1. 设置资源加载器this.resourceLoader = resourceLoader,通常为 null,后续会根据环境动态加载。
    2. 设置主配置类this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)),传入 MyApplication.class
    3. 推断应用类型this.webApplicationType = WebApplicationType.deduceFromClasspath(),通过类路径检测是否包含 Servlet 或 Reactive 相关类,决定是 SERVLETREACTIVE 还是 NONE
    4. 初始化监听器和初始化器
      • setInitializers() 调用 getSpringFactoriesLoader().loadFactoryNames(ApplicationContextInitializer.class)META-INF/spring.factories 加载初始化器。
      • setListeners() 加载 ApplicationListener

面试考点:如何自定义 ApplicationContextInitializerApplicationListener?答案是实现对应接口并在 spring.factories 中注册。


第二步:run 方法执行

SpringApplication.run() 是启动的核心逻辑,包含多个子步骤。

2.1 配置环境准备
  • 组件org.springframework.boot.SpringApplication
  • 功能prepareEnvironment(listeners, applicationArguments)
  • 细节
    1. 创建环境ConfigurableEnvironment environment = getOrCreateEnvironment(),根据 webApplicationType 创建 StandardEnvironment(非 Web)或 StandardServletEnvironment(Web)。
    2. 加载配置configureEnvironment(environment, args),绑定命令行参数到环境变量。
    3. 触发事件listeners.environmentPrepared(environment),通过 SpringApplicationRunListeners 广播 ApplicationEnvironmentPreparedEvent

面试考点:环境变量如何加载?PropertySource 的加载顺序是什么?(答案:命令行参数 > 系统属性 > 配置文件)

2.2 创建 ApplicationContext
  • 组件org.springframework.boot.SpringApplication
  • 功能createApplicationContext()
  • 细节
    • 根据 webApplicationType
      • SERVLET:创建 AnnotationConfigServletWebServerApplicationContext
      • REACTIVE:创建 AnnotationConfigReactiveWebServerApplicationContext
      • NONE:创建 AnnotationConfigApplicationContext
    • 使用 ApplicationContextFactory 创建上下文。

面试考点ApplicationContextBeanFactory 的区别?Spring Boot 如何选择上下文类型?

2.3 准备 ApplicationContext
  • 组件org.springframework.boot.SpringApplication
  • 功能prepareContext(context, environment, listeners, applicationArguments, banner)
  • 细节
    1. 绑定环境context.setEnvironment(environment)
    2. 注册配置类context.getBeanDefinitionRegistry().registerBeanDefinition() 注册主配置类。
    3. 加载 Bean 定义load(context, sources),通过 BeanDefinitionLoader 解析注解配置。
    4. 触发事件listeners.contextPrepared(context)
2.4 刷新 ApplicationContext
  • 组件org.springframework.context.ConfigurableApplicationContext
  • 功能refresh()
  • 细节
    1. BeanFactory 准备prepareBeanFactory() 配置类加载器、添加后处理器(如 ConfigurationClassPostProcessor)。
    2. 后处理器执行invokeBeanFactoryPostProcessors() 处理 @Configuration@Bean
    3. 注册 BeanPostProcessorregisterBeanPostProcessors()
    4. 初始化消息源initMessageSource()
    5. 初始化事件发布者initApplicationEventMulticaster()
    6. 启动嵌入式 Web 服务器
      • 组件org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
      • 功能createWebServer(),默认使用 Tomcat(TomcatServletWebServerFactory)。
    7. Bean 创建finishBeanFactoryInitialization() 实例化所有单例 Bean。

面试考点refresh() 的 12 个步骤是什么?嵌入式 Tomcat 是如何启动的?

2.5 启动后处理
  • 组件org.springframework.boot.SpringApplication
  • 功能afterRefresh(context, args)
  • 细节
    • 触发 ApplicationStartedEventApplicationReadyEvent

请求链路图

以下是 Spring Boot 启动的请求链路图,使用 Mermaid 语法绘制:

sequenceDiagram
    participant M as Main
    participant SA as SpringApplication
    participant ENV as Environment
    participant CTX as ApplicationContext
    participant WS as WebServer

    M->>SA: run(MyApplication.class, args)
    SA->>SA: new SpringApplication()
    SA->>ENV: getOrCreateEnvironment()
    SA->>ENV: configureEnvironment(args)
    SA->>CTX: createApplicationContext()
    SA->>CTX: prepareContext()
    CTX->>CTX: refresh()
    CTX->>WS: createWebServer()
    WS-->>CTX: Web Server Started
    CTX-->>SA: ApplicationReadyEvent
    SA-->>M: Application Running

总结

Spring Boot 的启动过程可以总结为以下关键步骤:

  1. 实例化 SpringApplication:加载初始化器和监听器。
  2. 环境准备:配置 Environment
  3. 上下文创建与刷新:初始化 ApplicationContext 并加载 Bean。
  4. Web 服务器启动:嵌入式容器(如 Tomcat)启动。
  5. 事件广播:通知应用就绪。