SpringBoot自动装配原理
Spring Boot 自动装配是其最核心、最具革命性的特性之一,它极大地简化了 Spring 应用的开发。其核心原理可以概括为:“约定优于配置” 和 “自动发现与注册”。
下面我们通过一个清晰的流程和核心源码解析来深入理解它。
一、核心思想
在没有自动装配之前,我们需要在 XML 或 Java 配置类中手动声明大量的 Bean(如 DataSource、EntityManagerFactory、TransactionManager 等)。Spring Boot 自动装配的目标是:当项目的 Classpath 下存在某个特定的类、配置或依赖时,Spring Boot 会自动为我们配置好这些 Bean,而无需我们手动编写配置代码。
二、实现原理详解
自动装配的实现主要依赖于以下几个核心组件:
- @SpringBootApplication 注解
- @EnableAutoConfiguration 注解
- spring.factories 文件
- @Conditional 系列条件注解
让我们通过启动流程来串联这些组件:
步骤 1:启动入口
每个 Spring Boot 应用的启动类上都有一个 @SpringBootApplication 注解。
@SpringBootApplication public class SpringSecurityApplication { public static void main(String[] args) { SpringApplication.run(SpringSecurityApplication.class, args); } }
@SpringBootApplication 是一个复合注解,它包含了许多其他注解,其中最关键的一个就是@EnableAutoConfiguration。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @SpringBootConfiguration @EnableAutoConfiguration // 关键注解! @ComponentScan public @interface SpringBootApplication { // ... }
步骤 2:开启自动配置
@EnableAutoConfiguration 是开启自动装配的“开关”。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) // 核心! public @interface EnableAutoConfiguration { // ... }
这个注解的核心是 @Import(AutoConfigurationImportSelector.class)。@Import 是 Spring 框架的注解,用于向容器中导入组件。这里导入了一个 AutoConfigurationImportSelector。
步骤 3:自动配置选择器
AutoConfigurationImportSelector 是整个自动装配过程的“大脑”。它的 selectImports 方法负责决定需要向 Spring 容器中导入哪些自动配置类。
public class AutoConfigurationImportSelector implements ... { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { // 核心方法:获取所有需要自动配置的类的全限定名 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); // ... (后续会有去重、过滤等操作) return StringUtils.toStringArray(configurations); } protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { // 从 spring.factories 文件中加载配置 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); return configurations; } protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; } }
关键点在于 SpringFactoriesLoader.loadFactoryNames(...) 这一行。它会去扫描所有依赖 jar 包中的 META-INF/spring.factories 文件。
步骤 4:spring.factories - 自动配置的清单
spring.factories 是一个标准的 Java properties 文件,格式为 `key=value1,value2,value3`。
在 spring-boot-autoconfigure 这个核心 jar 包的 META-INF/spring.factories 文件中,有一个以 EnableAutoConfiguration 为 key 的配置项,它的 value 是一个长长的、用逗号分隔的自动配置类的全限定名列表。
示例 (META-INF/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,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ ... (这里列出了上百个自动配置类)
AutoConfigurationImportSelector 就是通过读取这个文件,获取了所有候选的自动配置类。
步骤 5:条件注解 - 按需加载
Spring Boot 不可能把所有 spring.factories 里定义的配置类都进行加载,否则你的应用会包含大量你不需要的 Bean,导致内存浪费和启动缓慢。
条件注解 (@Conditional) 就是用来解决这个问题的。它们被标注在每一个自动配置类上,只有当条件满足时,这个自动配置类才会生效,其内部定义的 Bean 才会被创建。
常见的条件注解:
@ConditionalOnClass:当 Classpath 下存在指定的类时生效。
@ConditionalOnMissingBean:当 Spring 容器中不存在指定类型的 Bean 时生效。(这为我们提供了覆盖默认 Bean 的机会)
@ConditionalOnProperty:当指定的配置属性有特定值时生效。
@ConditionalOnWebApplication:当应用是 Web 应用时生效。
@ConditionalOnJava:当运行在指定的 Java 版本时生效。
步骤 6:自动配置类的工作
让我们以 DataSourceAutoConfiguration 为例,看看一个典型的自动配置类长什么样:
@Configuration(proxyBeanMethods = false) // 声明这是一个配置类 @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) // 条件1:存在相关类 @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory") // 条件2:不存在 R2DBC 连接工厂 @EnableConfigurationProperties(DataSourceProperties.class) // 使 DataSourceProperties 配置属性生效 public class DataSourceAutoConfiguration { @Configuration @Conditional(EmbeddedDatabaseCondition.class) // 内嵌数据库条件 @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import(EmbeddedDataSourceConfiguration.class) protected static class EmbeddedDatabaseConfiguration { } @Configuration @Conditional(PooledDataSourceCondition.class) // 连接池数据源条件 @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class }) protected static class PooledDataSourceConfiguration { } // ... 其他内部配置类 }
这个配置类做了以下几件事:
1. 只有在 Classpath 下存在 DataSource 和 EmbeddedDatabaseType 类时(即引入了数据库驱动),它才会生效。
2. 它导入了 DataSourceProperties 类,这个类绑定了 application.properties 中以 spring.datasource 为前缀的配置。
3. 它定义了两个内部配置类,分别用于创建内嵌数据库(如 H2)和连接池数据源(如 HikariCP)。具体使用哪个,由 PooledDataSourceCondition 等条件决定。
4. 只有在容器中不存在 DataSource 类型的 Bean 时,它才会创建默认的 Bean。这允许我们自己在配置类中定义一个 DataSource Bean 来完全覆盖默认的自动配置。
三、总结与流程图
自动装配流程总结:
- 启动应用:@SpringBootApplication -> @EnableAutoConfiguration。
- 导入选择器:@Import(AutoConfigurationImportSelector.class) 开始工作。
- 加载清单:AutoConfigurationImportSelector 读取所有 jar 包的 META-INF/spring.factories 文件,获取 EnableAutoConfiguration 对应的所有自动配置类的全类名。
- 过滤筛选:根据这些配置类上标注的 @Conditional 系列条件注解,按需进行筛选,只加载满足当前应用环境(Classpath、配置、已存在的 Bean 等)的配置类。
- 执行配置:被选中的自动配置类开始执行,向容器中注入预先定义好的、满足生产需求的 Bean。
四、如何调试和查看自动装配
- 开启调试日志:在 application.properties 中添加 debug=true。启动时,控制台会打印出所有自动配置类的评估报告,分为两部分:
- Positive matches:已启用的自动配置。
- Negative matches:未启用的自动配置及原因。
- 查看已启用的配置:使用 Spring Actuator 的 /conditions 端点(如果引入了 Actuator 依赖),它可以提供一个更详细的 HTML 报告。

浙公网安备 33010602011771号