一、核心思想:约定优于配置
自动装配的本质是 “约定优于配置”。Spring Boot 根据你引入的依赖(Jar 包),自动推测并组装你需要的 Bean,从而极大地减少了繁琐的 XML 或 Java 配置。
二、自动装配的“总开关”:@SpringBootApplication
一切始于启动类上的 @SpringBootApplication 注解。
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}这个注解是一个复合注解,它包含了几个至关重要的注解:
@SpringBootConfiguration
@EnableAutoConfiguration // <--- 自动装配的核心入口
@ComponentScan
public @interface SpringBootApplication {
// ...
}其中,@EnableAutoConfiguration 就是开启自动装配大门的钥匙。
三、自动装配的核心原理与流程
整个自动装配过程可以概括为:通过 @EnableAutoConfiguration 触发,读取 META-INF/spring.factories 文件,加载所有声明的自动配置类,然后根据一系列条件注解(如 @ConditionalOnClass)进行过滤,最终将符合条件的配置类中定义的 Bean 加载到 IoC 容器中。
下面是详细的步骤分解:
步骤 1:触发自动配置
@EnableAutoConfiguration 注解本身又导入了一个关键的选择器:AutoConfigurationImportSelector。
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// ...
}AutoConfigurationImportSelector 是自动装配逻辑的“大脑”。
步骤 2:加载候选配置类
在 Spring Boot 应用启动过程中(具体是在 ConfigurationClassPostProcessor 处理配置类时),会调用 AutoConfigurationImportSelector 的 selectImports 方法。
这个方法的核心工作是:
- 通过
SpringFactoriesLoader工具类,从 classpath 下所有 Jar 包的META-INF/spring.factories配置文件中,读取EnableAutoConfiguration这个 key 对应的所有配置类的全限定名。 - 这些配置类就是“候选”的自动配置类。
以 spring-boot-autoconfigure-2.x.x.RELEASE.jar 为例,其 spring.factories 文件片段如下:
# 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类中自己定义了一个DataSourceBean,那么自动配置的DataSource就不会被加载。
- 例如:Spring Boot 自动配置了一个
@ConditionalOnProperty:指定的配置属性有指定的值时,配置才生效。@ConditionalOnWebApplication/@ConditionalOnNotWebApplication:根据是否是 Web 应用来决定是否加载。
过滤过程: Spring Boot 在真正加载这些配置类之前,会使用 ConditionEvaluator 来逐一检查每个配置类上的条件注解。只有所有条件都满足的配置类,才会被最终解析并导入到 Spring 容器中。
步骤 4:执行自动配置
经过过滤后,剩下的自动配置类就会被 Spring 容器正常加载,它们本身就是 @Configuration 配置类。这些类中定义了大量的 @Bean 方法,这些 Bean 就被创建并加入到 IoC 容器中,供我们使用。
四、自动装配的“顺序”问题
你可能会问,这么多自动配置类,它们的执行顺序是怎样的?
@AutoConfigureOrder注解: 这个注解类似于@Order,可以定义配置类的加载顺序。但实际上,自动配置类很少使用它,因为自动装配更多地依赖于条件注解,而不是严格的顺序。@AutoConfigureAfter/@AutoConfigureBefore: 这两个注解是 Spring Boot 为自动配置类提供的、更细粒度的顺序控制注解。@AutoConfigureAfter(A.class):表示本配置类必须在 A 配置类之后处理。@AutoConfigureBefore(B.class):表示本配置类必须在 B 配置类之前处理。- 使用场景:当 A 配置类定义的 Bean 是 B 配置类的依赖时,就需要确保 A 在 B 之前加载。
示例:
RabbitAutoConfiguration可能会标注@AutoConfigureAfter(MessageSourceAutoConfiguration.class),以确保消息源先配置好。隐式顺序: 大部分情况下,自动配置是“幂等”的,顺序并不重要。Bean 的最终覆盖权由
@ConditionalOnMissingBean决定。后定义的 Bean 如果满足条件,可以覆盖先定义的 Bean。而用户通过@Configuration定义的配置类,其优先级默认高于自动配置类,这也是为什么我们可以轻松地用自定义配置覆盖默认配置的原因。
五、总结与流程图
核心流程总结:
- 启动:由
@SpringBootApplication->@EnableAutoConfiguration触发。 - 加载:
AutoConfigurationImportSelector扫描spring.factories,获取所有候选配置类。 - 过滤:利用
@ConditionalOnXxx条件注解,根据当前项目的类路径、已有 Bean、配置属性等环境信息,进行筛选,得到最终需要生效的配置类。 - 装配:加载生效的配置类,将其中定义的 Bean 注册到 IoC 容器。
流程图:
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 的默认行为。