Skip to content

一、核心思想:约定优于配置

自动装配的本质是 “约定优于配置”。Spring Boot 根据你引入的依赖(Jar 包),自动推测并组装你需要的 Bean,从而极大地减少了繁琐的 XML 或 Java 配置。


二、自动装配的“总开关”:@SpringBootApplication

一切始于启动类上的 @SpringBootApplication 注解。

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

这个注解是一个复合注解,它包含了几个至关重要的注解:

java
@SpringBootConfiguration
@EnableAutoConfiguration // <--- 自动装配的核心入口
@ComponentScan
public @interface SpringBootApplication {
    // ...
}

其中,@EnableAutoConfiguration 就是开启自动装配大门的钥匙。


三、自动装配的核心原理与流程

整个自动装配过程可以概括为:通过 @EnableAutoConfiguration 触发,读取 META-INF/spring.factories 文件,加载所有声明的自动配置类,然后根据一系列条件注解(如 @ConditionalOnClass)进行过滤,最终将符合条件的配置类中定义的 Bean 加载到 IoC 容器中。

下面是详细的步骤分解:

步骤 1:触发自动配置

@EnableAutoConfiguration 注解本身又导入了一个关键的选择器:AutoConfigurationImportSelector

java
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // ...
}

AutoConfigurationImportSelector 是自动装配逻辑的“大脑”。

步骤 2:加载候选配置类

在 Spring Boot 应用启动过程中(具体是在 ConfigurationClassPostProcessor 处理配置类时),会调用 AutoConfigurationImportSelectorselectImports 方法。

这个方法的核心工作是:

  1. 通过 SpringFactoriesLoader 工具类,从 classpath 下所有 Jar 包的 META-INF/spring.factories 配置文件中,读取 EnableAutoConfiguration 这个 key 对应的所有配置类的全限定名。
  2. 这些配置类就是“候选”的自动配置类。

spring-boot-autoconfigure-2.x.x.RELEASE.jar 为例,其 spring.factories 文件片段如下:

properties
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
// ... 这里列出了上百个配置类

此时,Spring Boot 拿到了一个非常长的、所有可能的自动配置类列表。

步骤 3:过滤与条件装配

如果直接把所有候选配置类都加载,会导致大量不必要的 Bean 被创建,甚至出现 ClassNotFoundException(比如你没有引入 Redis 依赖,却加载了 Redis 的配置类)。

因此,最关键的一步——“按需加载” 发生了。Spring Boot 通过一系列 @Conditional 条件注解 来过滤这个候选列表。

这些条件注解是自动装配的灵魂:

  • @ConditionalOnClass:类路径下存在指定的类时,配置才生效。
    • 例如:DataSourceAutoConfiguration 上就有 @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }),只有当你引入了数据库相关的 Jar 包(包含了 DataSource 类),配置才会被加载。
  • @ConditionalOnBean:容器中存在指定的 Bean 时,配置才生效。
  • @ConditionalOnMissingBean:容器中不存在指定的 Bean 时,配置才生效。这是实现配置覆盖的关键。
    • 例如:Spring Boot 自动配置了一个 DataSource,但如果你在自定义的 @Configuration 类中自己定义了一个 DataSource Bean,那么自动配置的 DataSource 就不会被加载。
  • @ConditionalOnProperty:指定的配置属性有指定的值时,配置才生效。
  • @ConditionalOnWebApplication / @ConditionalOnNotWebApplication:根据是否是 Web 应用来决定是否加载。

过滤过程: Spring Boot 在真正加载这些配置类之前,会使用 ConditionEvaluator 来逐一检查每个配置类上的条件注解。只有所有条件都满足的配置类,才会被最终解析并导入到 Spring 容器中。

步骤 4:执行自动配置

经过过滤后,剩下的自动配置类就会被 Spring 容器正常加载,它们本身就是 @Configuration 配置类。这些类中定义了大量的 @Bean 方法,这些 Bean 就被创建并加入到 IoC 容器中,供我们使用。


四、自动装配的“顺序”问题

你可能会问,这么多自动配置类,它们的执行顺序是怎样的?

  1. @AutoConfigureOrder 注解: 这个注解类似于 @Order,可以定义配置类的加载顺序。但实际上,自动配置类很少使用它,因为自动装配更多地依赖于条件注解,而不是严格的顺序。

  2. @AutoConfigureAfter / @AutoConfigureBefore: 这两个注解是 Spring Boot 为自动配置类提供的、更细粒度的顺序控制注解。

    • @AutoConfigureAfter(A.class):表示本配置类必须在 A 配置类之后处理。
    • @AutoConfigureBefore(B.class):表示本配置类必须在 B 配置类之前处理。
    • 使用场景:当 A 配置类定义的 Bean 是 B 配置类的依赖时,就需要确保 A 在 B 之前加载。

    示例:RabbitAutoConfiguration 可能会标注 @AutoConfigureAfter(MessageSourceAutoConfiguration.class),以确保消息源先配置好。

  3. 隐式顺序: 大部分情况下,自动配置是“幂等”的,顺序并不重要。Bean 的最终覆盖权由 @ConditionalOnMissingBean 决定。后定义的 Bean 如果满足条件,可以覆盖先定义的 Bean。而用户通过 @Configuration 定义的配置类,其优先级默认高于自动配置类,这也是为什么我们可以轻松地用自定义配置覆盖默认配置的原因。


五、总结与流程图

核心流程总结:

  1. 启动:由 @SpringBootApplication -> @EnableAutoConfiguration 触发。
  2. 加载AutoConfigurationImportSelector 扫描 spring.factories,获取所有候选配置类。
  3. 过滤:利用 @ConditionalOnXxx 条件注解,根据当前项目的类路径已有 Bean配置属性等环境信息,进行筛选,得到最终需要生效的配置类。
  4. 装配:加载生效的配置类,将其中定义的 Bean 注册到 IoC 容器。

流程图:

mermaid
graph TD
    A[@SpringBootApplication] --> B[@EnableAutoConfiguration];
    B --> C[AutoConfigurationImportSelector];
    C --> D[扫描所有 META-INF/spring.factories];
    D --> E[获取 EnableAutoConfiguration 对应的候选配置类列表];
    E --> F{条件注解过滤<br>@ConditionalOnClass等};
    F -- 条件满足 --> G[加载有效的自动配置类];
    F -- 条件不满足 --> H[丢弃该配置类];
    G --> I[执行@Bean方法, 注册Bean到IoC容器];
    I --> J[自动装配完成];

六、如何调试和查看

  • 开启调试日志:在 application.properties 中添加 debug=true。启动时,控制台会打印两份报告:
    • Positive matches:报告哪些自动配置类生效了
    • Negative matches:报告哪些自动配置类未生效及其原因。
  • 查看已生效的配置类:使用 Actuator 的 /conditions 端点(需要引入 spring-boot-starter-actuator 依赖),它可以提供一个更详细的 HTML 报告。

通过理解这个原理,你就能明白为什么“引入一个 Starter,功能自然就有了”,以及如何通过自定义配置来覆盖 Spring Boot 的默认行为。

/src/technology/dateblog/2025/10/20251027-spring-boot-%E5%90%AF%E5%8A%A8%E6%97%B6%E7%9A%84%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D%E5%8E%9F%E7%90%86%E5%92%8C%E9%A1%BA%E5%BA%8F.html