目录
示例:DataSourceAutoConfiguration
一、引言
在Java开发领域,Spring Boot以其独特的自动装配机制,彻底改变了传统开发模式。过去,开发者常常被Spring项目的复杂配置所困扰,版本冲突和配置错误更是家常便饭。然而,Spring Boot的自动装配功能的出现,使得项目几乎可以实现“零配置”启动,让开发者能够将主要精力集中在业务逻辑的实现上,从而极大地提高了开发效率。接下来,我们将深入剖析Spring Boot自动装配背后的原理。
二、Spring Boot自动装配揭秘
1.自动装配的定义
Spring Boot的自动装配是一套智能且高效的依赖注入与配置协调系统,遵循“约定优于配置”的原则。在项目启动阶段,它能够自动识别类路径下的各类组件及配置信息,并依据预先设定的精细规则完成装配任务。
2.@SpringBootApplication注解
自动配置的起点通常是@SpringBootApplication注解,它是一个组合注解,包含了三个重要注解:
@SpringBootApplication
public class SpringBootDemo1031Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemo1031Application.class, args);
}
}

- @SpringBootConfiguration:等同于@Configuration,为自动装配的配置环节搭建基础框架。
- @EnableAutoConfiguration:自动配置的核心,通过@Import(AutoConfigurationImportSelector.class)引入AutoConfigurationImportSelector,实现智能的自动配置。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
AutoConfigurationImportSelector 类的继承体系如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
}
public interface DeferredImportSelector extends ImportSelector {
}
public interface ImportSelector {
String[] selectImports(AnnotationMetadata var1);
}
可以看出,AutoConfigurationImportSelector类实现了ImportSelector接口,也就实现了这个接口中的selectImports方法,该方法主要用于获取所有符合条件的类的全限类名,这些类需要被加载到IOC容器中。
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 1.检查是否启用自动配置
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
// 2.获取所有需要装配的bean
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
getAutoConfigurationEntry方法通过一系列步骤,包括检查自动配置是否启用、获取候选配置、去除重复项、获取排除配置、检查排除的类是否有效、移除排除项、过滤配置,最终生成一个包含自动配置类和排除配置类的AutoConfigurationEntry对象。这个方法是Spring Boot自动配置功能的核心,它确保了只有符合条件的自动配置类被加载到Spring应用上下文中。
/**
* 获取自动配置入口信息,包括需要加载的自动配置类和需要排除的配置类。
*
* @param annotationMetadata 当前注解的元数据,提供了关于注解的信息,用于决定哪些自动配置类应该被导入。
* @return 包含自动配置类和排除配置类的AutoConfigurationEntry对象。
*/
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
// 1. 如果自动配置没有被启用,则返回一个空的AutoConfigurationEntry对象
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
// 2. 从注解元数据中获取注解属性
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 3. 获取所有候选的自动配置类名
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 4. 去除候选配置中的重复项
configurations = this.removeDuplicates(configurations);
// 获取需要被排除的自动配置类名
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
// 检查排除的类是否在候选配置中,如果不在,则抛出异常
this.checkExcludedClasses(configurations, exclusions);
// 从候选配置中移除排除项
configurations.removeAll(exclusions);
// 使用ConfigurationClassFilter过滤候选配置
configurations = this.getConfigurationClassFilter().filter(configurations);
// 触发自动配置导入事件,通知所有监听器自动配置类即将被导入
this.fireAutoConfigurationImportEvents(configurations, exclusions);
// 创建并返回一个新的AutoConfigurationEntry对象,包含过滤后的配置和排除配置
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
- @ComponentScan:负责搜索项目中的组件,为后续装配工作提供资源支持。
3.spring.factories 文件
Spring Boot 的自动配置是通过 spring.factories 文件来实现的。spring.factories 文件位于 META-INF 目录下,它是一个标准的 Java 属性文件,用于定义自动配置类。
在 Spring Boot 的 spring-boot-autoconfigure 模块中,META-INF/spring.factories 文件定义了大量的自动配置类。例如:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
...
这些自动配置类会根据项目的依赖和配置,自动配置相应的 Bean。
4.条件装配(@Conditional系列注解)
Spring Boot并非盲目加载所有自动配置类,每个自动配置类通常都会运用@Conditional系列注解来实现有条件的加载。这极大地优化了资源配置,让自动装配更贴合项目实际需求。常见的条件注解有:
- @ConditionalOnClass:当类路径中存在某个类时才生效。
- @ConditionalOnMissingBean:当Spring上下文中不存在某个Bean时才生效。
- @ConditionalOnProperty:当某个配置属性满足特定条件时才生效。
- @ConditionalOnBean:当Spring上下文中存在某个Bean时才生效。
示例:DataSourceAutoConfiguration
Spring Boot 中DataSourceAutoConfiguration 是配置数据源的自动配置类,它的源码如下:
@Configuration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.class})
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
@ConditionalOnClass(DataSource.class):只有当类路径下存在 DataSource 类时,才进行数据源的自动配置。
@ConditionalOnMissingBean:如果 Spring 上下文中没有其他 DataSource Bean,则自动配置一个。
只有当这些条件满足时,DataSourceAutoConfiguration才会被实例化和执行,这意味着Spring Boot在启动过程中,并不会盲目的加载spring.factories中的每一个自动配置类,而是基于运行环境和应用的配置智能选择激活配置。
三、自动配置的工作流程
- 收集自动配置类:启动时,AutoConfigurationImportSelector从spring.factories文件中读取所有的自动配置类,并通过@Import导入这些类。
- 条件检查:自动配置类的加载不是无条件的,Spring Boot会根据@Conditional注解进行条件检查,确保只有符合条件的自动配置类才会生效。
- 注入所需的Bean:一旦自动配置类通过条件检查,Spring Boot就会根据这些配置类注册所需的Bean。
- 允许用户覆盖自动配置:自动配置并不是强制的。用户可以通过显式声明自己的Bean来覆盖自动配置的默认行为。
四、Spring Boot自动装配的实际案例
- Web应用自动配置:如DispatcherServletAutoConfiguration负责自动配置Spring MVC的核心组件。
- 数据库连接池自动配置:如DataSourceAutoConfiguration和DataSourceProperties共同负责自动配置数据源。
五、Spring Boot自动装配的优势
- 提高开发效率:开发者摆脱繁琐配置工作,聚焦业务功能迭代。
- 降低学习成本:自动装配机制降低入门难度,使新手无需陷入配置困境。
- 保证一致性:自动装配由框架统一管理,不同项目结构与配置趋于一致,便于团队协作和代码维护。
六、总结
Spring Boot的自动装配机制为Java开发注入了强大动力。深入理解其原理和流程,不仅有助于开发者更高效地开发项目,还为进一步探索定制化自动装配、拓展框架应用边界提供了可能。随着技术的不断进步,相信Spring Boot的自动装配机制将会在未来发挥更大的作用。

1929

被折叠的 条评论
为什么被折叠?



