Spring Boot 3.x 与 Spring Boot 2.x 自动配置实现原理 分析。
🧠 一、Spring Boot 2.x 自动配置原理(基于 spring.factories
)
✅ 1. 自动配置入口:@EnableAutoConfiguration
Spring Boot 2.x 的自动配置通过 @EnableAutoConfiguration
注解触发:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
✅ 2. 自动配置类加载机制:SpringFactoriesLoader
Spring Boot 2.x 使用 SpringFactoriesLoader
从 META-INF/spring.factories
文件中加载自动配置类:
public final class SpringFactoriesLoader {
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
ClassLoader classLoaderToUse = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
Enumeration<URL> urls = classLoaderToUse.getResources(FACTORIES_RESOURCE_LOCATION); // 即 "META-INF/spring.factories"
List<String> result = new ArrayList<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryTypeName);
if (factoryClassNames != null) {
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
}
return result;
}
}
✅ 3. 自动配置类的筛选机制
Spring Boot 会加载所有 spring.factories
中的自动配置类,并通过 @Conditional
系列注解(如 @ConditionalOnClass
、@ConditionalOnMissingBean
)筛选是否生效。
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
List<String> configurations = getCandidateConfigurations(annotationMetadata, null);
configurations = removeDuplicates(configurations);
Set<String> autoConfigurationGroup = getAutoConfigurationGroup(annotationMetadata, configurations);
return StringUtils.toStringArray(autoConfigurationGroup);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 通过 SpringFactoriesLoader 加载 spring.factories 中的自动配置类
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories");
return configurations;
}
}
✅ 4. spring.factories
示例
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.MyAutoConfiguration
✅ 5. 自动配置类示例
@Configuration
@ConditionalOnClass(MyService.class)
@ConditionalOnMissingBean
public class MyAutoConfiguration {
@Bean
public MyService myService() {
return new MyService();
}
}
🔄 二、Spring Boot 3.x 自动配置原理(基于 AutoConfiguration.imports
)
✅ 1. 移除 spring.factories
,使用 AutoConfiguration.imports
Spring Boot 3.x 不再依赖 spring.factories
,而是使用新的配置方式 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
。
✅ 示例文件路径:
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
✅ 文件内容(每行一个自动配置类):
com.example.autoconfig.MyAutoConfiguration
✅ 2. 自动配置类加载机制:AutoConfigurationImportSelector
改进
Spring Boot 3.x 中,AutoConfigurationImportSelector
内部逻辑发生变化,改为直接读取 AutoConfiguration.imports
文件。
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
List<String> configurations = getCandidateConfigurations(annotationMetadata, null);
configurations = removeDuplicates(configurations);
Set<String> autoConfigurationGroup = getAutoConfigurationGroup(annotationMetadata, configurations);
return StringUtils.toStringArray(autoConfigurationGroup);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList<>();
try {
// 新版:直接读取 AutoConfiguration.imports 文件
Enumeration<URL> urls = getClass().getClassLoader().getResources("META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports");
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = new Properties();
properties.load(url.openStream());
properties.forEach((key, value) -> configurations.add((String) key));
}
} catch (IOException ex) {
throw new IllegalStateException("Failed to load auto-configuration imports", ex);
}
return configurations;
}
}
✅ 3. 条件注解机制保持不变
Spring Boot 3.x 依然使用 @Conditional
系列注解进行条件装配:
@Configuration
@ConditionalOnClass(MyService.class)
@ConditionalOnMissingBean
public class MyAutoConfiguration {
@Bean
public MyService myService() {
return new MyService();
}
}
✅ 4. 支持 Java 17 的新特性(如 getDeclaredConstructors()
)
Spring Boot 3.x 要求使用 JDK 17 或更高版本,因此内部反射调用方式有所变化:
// Spring Boot 2.x(JDK 8 兼容)
Method method = clazz.getDeclaredMethod("someMethod");
// Spring Boot 3.x(JDK 17+)
Constructor<?> constructor = clazz.getDeclaredConstructors()[0];
📦 三、Spring Boot 3.x 自动配置的完整流程
✅ 1. 启动类:@SpringBootApplication
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
✅ 2. @SpringBootApplication
的作用
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
@EnableAutoConfiguration
:触发自动配置@ComponentScan
:扫描组件@SpringBootConfiguration
:标记为配置类
✅ 3. @EnableAutoConfiguration
的实现
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
@Import(AutoConfigurationImportSelector.class)
:导入自动配置选择器
✅ 4. AutoConfigurationImportSelector
的改进(Spring Boot 3.x)
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
List<String> configurations = getCandidateConfigurations(annotationMetadata, null);
configurations = removeDuplicates(configurations);
Set<String> autoConfigurationGroup = getAutoConfigurationGroup(annotationMetadata, configurations);
return StringUtils.toStringArray(autoConfigurationGroup);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList<>();
try {
// 新版:读取 AutoConfiguration.imports 文件
Enumeration<URL> urls = getClass().getClassLoader().getResources("META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports");
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = new Properties();
properties.load(url.openStream());
properties.forEach((key, value) -> configurations.add((String) key));
}
} catch (IOException ex) {
throw new IllegalStateException("Failed to load auto-configuration imports", ex);
}
return configurations;
}
}
✅ 5. AutoConfiguration.imports
文件格式(Spring Boot 3.x)
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.autoconfig.MyAutoConfiguration
🧱 四、Spring Boot 2.x 与 3.x 自动配置的核心差异
特性 | Spring Boot 2.x | Spring Boot 3.x |
---|---|---|
自动配置文件 | META-INF/spring.factories | META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |
配置加载方式 | SpringFactoriesLoader | Properties.load() 直接读取 |
支持的 JDK 版本 | JDK 8 ~ 17(兼容旧版本) | JDK 17+(不兼容 JDK 8) |
自动配置类加载方式 | 通过 SpringFactoriesLoader 加载 | 通过 Properties 文件直接读取 |
性能优化 | 无显著优化 | 避免多次加载 spring.factories ,提升启动速度 |
模块化支持 | 不支持 JPMS(Java Platform Module System) | 支持 JPMS,兼容模块化项目 |
反射 API 使用 | 使用 getDeclaredMethod() | 使用 getDeclaredConstructors() (适配 JDK 17) |
🔄 五、Spring Boot 3.x 自动配置的源码执行流程(简化版)
@SpringBootApplication
└── @EnableAutoConfiguration
└── @Import(AutoConfigurationImportSelector.class)
└── AutoConfigurationImportSelector.selectImports()
└── getCandidateConfigurations()
└── 读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件
└── 加载自动配置类(如 MyAutoConfiguration)
└── 过滤重复配置
└── 按条件筛选(@ConditionalOnClass、@ConditionalOnMissingBean 筃
└── 注册为 BeanDefinition 并注册到容器
🧩 六、Spring Boot 3.x 自动配置的源码关键类
类名 | 作用 |
---|---|
AutoConfigurationImportSelector | Spring Boot 自动配置的核心类,负责加载自动配置类 |
AutoConfiguration.imports | Spring Boot 3.x 的自动配置类配置文件 |
SpringFactoriesLoader | Spring Boot 2.x 使用的自动配置类加载器 |
AutoConfigurationGroup | 负责按条件筛选自动配置类 |
ConditionEvaluator | 评估 @Conditional 注解是否满足条件 |
🧱 七、Spring Boot 3.x 自动配置的性能优化
✅ 1. 避免重复加载 spring.factories
Spring Boot 3.x 使用 AutoConfiguration.imports
替代 spring.factories
,避免了多个 spring.factories
文件的合并和去重操作,提升加载效率。
✅ 2. 支持模块化项目(JPMS)
Spring Boot 3.x 完全支持 Java 9+ 的模块化系统(JPMS),自动配置类可以在模块中声明,无需手动配置。
✅ 3. JDK 17 兼容性优化
Spring Boot 3.x 使用 JDK 17 的新特性,如 getDeclaredConstructors()
替代 getDeclaredMethods()
,提高反射性能。
📦 八、Spring Boot 3.x 自动配置迁移指南
✅ 1. 从 Spring Boot 2.x 迁移到 3.x
步骤 1:修改自动配置类的注册方式
Spring Boot 2.x:
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.MyAutoConfiguration
Spring Boot 3.x:
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.autoconfig.MyAutoConfiguration
步骤 2:更新依赖版本
确保所有依赖库已升级到支持 Spring Boot 3.x 的版本(如 Spring Boot 3.0+、Spring Framework 6.0+、Jakarta EE 9+)。
步骤 3:适配 JDK 17+
- 使用
getDeclaredConstructors()
替代getDeclaredMethods()
- 替换
javax.*
为jakarta.*
- 使用新的模块化方式构建项目(如
module-info.java
)
步骤 4:测试自动配置行为
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
MyService service = context.getBean(MyService.class);
service.doSomething(); // 验证自动配置是否生效
}
}
🧪 九、完整示例:Spring Boot 3.x 自动配置实现
1. 自动配置类定义
@Configuration
@ConditionalOnClass(MyService.class)
@ConditionalOnMissingBean
public class MyAutoConfiguration {
@Bean
public MyService myService() {
return new MyService();
}
}
2. 配置文件(Spring Boot 3.x)
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.autoconfig.MyAutoConfiguration
3. 使用自动配置类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
MyService service = context.getBean(MyService.class);
service.doSomething(); // 自动配置生效
}
}
✅ 十、总结
特性 | Spring Boot 2.x | Spring Boot 3.x |
---|---|---|
自动配置文件 | spring.factories | AutoConfiguration.imports |
自动配置类加载方式 | SpringFactoriesLoader | Properties.load() 直接读取 |
JDK 支持 | JDK 8 ~ 17 | JDK 17+ |
模块化支持 | 不支持 JPMS | 支持 JPMS |
反射 API 改进 | 使用 getDeclaredMethod() | 使用 getDeclaredConstructors() |
性能优化 | 无显著优化 | 避免多次加载 spring.factories |
条件注解机制 | 保持一致 | 保持一致 |
🧩 十一、扩展
-
Spring Boot 3.x 自动配置的源码路径:
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
org.springframework.boot.autoconfigure.AutoConfigurationGroup
-
Spring Boot 3.x 的官方迁移指南:
-
Spring Boot 3.x 的模块化支持:
- 支持 Java 9+ 模块化项目,自动配置类可以定义在模块中
-
Spring Boot 3.x 与 Jakarta EE 9+ 的兼容性:
- 所有
javax.*
包名替换为jakarta.*
- 所有