Spring Boot 自动配置实现原理

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 使用 SpringFactoriesLoaderMETA-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.xSpring Boot 3.x
自动配置文件META-INF/spring.factoriesMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
配置加载方式SpringFactoriesLoaderProperties.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 自动配置的源码关键类

类名作用
AutoConfigurationImportSelectorSpring Boot 自动配置的核心类,负责加载自动配置类
AutoConfiguration.importsSpring Boot 3.x 的自动配置类配置文件
SpringFactoriesLoaderSpring 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.xSpring Boot 3.x
自动配置文件spring.factoriesAutoConfiguration.imports
自动配置类加载方式SpringFactoriesLoaderProperties.load() 直接读取
JDK 支持JDK 8 ~ 17JDK 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.*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值