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 报告。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! 分享、互助 让互联网精神温暖你我
页:
[1]