问题

SpringBoot是如何实现自动配置的?

答案

1. 核心概念

SpringBoot的自动配置(Auto-Configuration)是其核心特性之一,通过约定优于配置的理念,在应用启动时自动加载和配置所需的Bean,无需手动编写大量配置代码。

2. 自动配置原理详解

(1) 核心注解:@SpringBootApplication

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@SpringBootApplication 是一个组合注解,包含三个核心注解:

@SpringBootConfiguration  // 标识为配置类(等同于@Configuration)
@EnableAutoConfiguration  // 启用自动配置
@ComponentScan            // 自动扫描组件
public @interface SpringBootApplication {
}

(2) @EnableAutoConfiguration工作机制

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

关键点:

  • @Import 导入 AutoConfigurationImportSelector,这是自动配置的核心类
  • AutoConfigurationImportSelector 会加载所有候选的自动配置类

(3) 自动配置类加载流程

SpringBoot 2.x 流程

// AutoConfigurationImportSelector.selectImports()方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
                                                  AnnotationAttributes attributes) {
    // 加载 META-INF/spring.factories 文件
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        EnableAutoConfiguration.class,
        getBeanClassLoader()
    );
    return configurations;
}

SpringBoot 3.x 流程(改进):

  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件加载
  • 采用更简洁的文本格式,每行一个配置类全限定名

(4) 条件注解控制加载

自动配置类通过条件注解决定是否生效:

@Configuration
@ConditionalOnClass(DataSource.class)  // classpath存在DataSource类才生效
@ConditionalOnMissingBean(DataSource.class)  // 不存在用户自定义DataSource才生效
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Bean
    @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "hikari")
    public DataSource hikariDataSource(DataSourceProperties properties) {
        return DataSourceBuilder.create()
                .type(HikariDataSource.class)
                .build();
    }
}

常用条件注解

  • @ConditionalOnClass / @ConditionalOnMissingClass:判断类是否存在
  • @ConditionalOnBean / @ConditionalOnMissingBean:判断Bean是否存在
  • @ConditionalOnProperty:判断配置属性值
  • @ConditionalOnResource:判断资源文件是否存在
  • @ConditionalOnWebApplication:判断是否为Web应用

(5) 配置属性绑定

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
    private String url;
    private String username;
    private String password;
    // getters and setters
}

通过 @EnableConfigurationProperties 将配置文件中的属性绑定到Java对象。

3. 完整执行流程

1. SpringApplication.run() 启动
                ↓
2. 刷新ApplicationContext
                ↓
3. 解析@SpringBootApplication注解
                ↓
4. 触发@EnableAutoConfiguration
                ↓
5. AutoConfigurationImportSelector.selectImports()
                ↓
6. 加载spring.factories/AutoConfiguration.imports
                ↓
7. 获取所有候选配置类(130+个)
                ↓
8. 去重、排序、过滤
                ↓
9. 条件注解评估(@ConditionalOnXxx)
                ↓
10. 注册符合条件的Bean到容器
                ↓
11. 绑定配置属性
                ↓
12. 完成自动配置

4. 实战示例:查看生效的自动配置

方法1:启用Debug日志

# application.properties
debug=true

输出:

============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:(生效的配置)
-----------------
   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required class 'javax.sql.DataSource'

Negative matches:(未生效的配置)
-----------------
   RedisAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations'

方法2:使用Actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

访问:http://localhost:8080/actuator/conditions

5. 性能优化考量

  1. 延迟加载:通过 @ConditionalOnClass 避免不必要的类加载
  2. 缓存机制:条件注解的评估结果会被缓存
  3. 排序优化:通过 @AutoConfigureAfter@AutoConfigureBefore 控制加载顺序
  4. 排除配置:显式排除不需要的自动配置减少启动时间
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

6. 面试答题要点总结

  1. 核心机制:通过 @EnableAutoConfiguration + AutoConfigurationImportSelector 加载配置类
  2. 加载源:从 spring.factories(2.x)或 AutoConfiguration.imports(3.x)读取候选配置
  3. 条件控制:利用 @ConditionalOnXxx 条件注解决定是否生效
  4. 属性绑定:通过 @ConfigurationProperties 绑定外部配置
  5. 设计优势:约定优于配置、按需加载、用户配置优先

一句话总结:SpringBoot通过 @EnableAutoConfiguration 触发 AutoConfigurationImportSelector 加载所有候选配置类,再通过条件注解筛选出符合当前环境的配置,最终自动注册Bean到Spring容器。