Tavio's blog Tavio's blog
首页
  • JVM底层原理
  • 邪恶多线程
  • MyBatis底层原理
  • Spring底层原理
  • MySQL的优化之路
  • ClickHouse的高性能
  • Redis的快速查询
  • RabbitMQ的生产
  • Kafka的高吞吐量
  • ES的入门到入坑
  • MySQL自增ID主键空洞
  • 前端实现长整型排序
  • MySQL无感换表
  • Redis延时双删
  • 高并发秒杀优惠卷
  • AOP无侵入式告警
  • 长短链接跳转
  • 订单超时取消
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Tavio Zhang

努力学习的小码喽
首页
  • JVM底层原理
  • 邪恶多线程
  • MyBatis底层原理
  • Spring底层原理
  • MySQL的优化之路
  • ClickHouse的高性能
  • Redis的快速查询
  • RabbitMQ的生产
  • Kafka的高吞吐量
  • ES的入门到入坑
  • MySQL自增ID主键空洞
  • 前端实现长整型排序
  • MySQL无感换表
  • Redis延时双删
  • 高并发秒杀优惠卷
  • AOP无侵入式告警
  • 长短链接跳转
  • 订单超时取消
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Spring Boot 自动配置
    • 一、核心认知:SpringBoot自动配置是什么?
    • 二、底层基石:自动配置依赖的核心技术
      • 2.1 Spring的JavaConfig与Bean注册机制
      • 2.2 Spring的条件注解(Conditional)
      • 2.3 Spring的SPI机制(Service Provider Interface)
    • 三、核心组件:自动配置的“齿轮”如何协同?
      • 3.1 入口注解:@SpringBootApplication
      • 3.2 核心开关:@EnableAutoConfiguration
      • 3.3 核心执行者:AutoConfigurationImportSelector
      • 3.4 配置文件:AutoConfiguration.imports(核心约定)
      • 3.5 自动配置类:@AutoConfiguration(最终的配置载体)
    • 四、完整流程:SpringBoot自动配置的“生命周期”
      • 4.1 流程拆解(共7步)
      • 4.2 流程图解
    • 五、实战验证:亲手拆解自动配置的生效过程
      • 5.1 案例1:验证DataSourceAutoConfiguration的自动生效
      • 5.2 案例2:验证@ConditionalOnMissingBean的覆盖机制
      • 5.3 案例3:验证自动配置类的排除机制
    • 六、扩展能力:自定义自动配置类
      • 6.1 自定义自动配置类步骤(共5步)
    • 七、常见问题:自动配置踩坑指南
      • 7.1 问题1:自动配置类不生效
      • 7.2 问题2:自定义Bean与自动配置Bean冲突
      • 7.3 问题3:配置文件中的配置项不生效
    • 八、总结:自动配置的核心本质
  • Spring Boot Bean 生命周期
  • Spring事务传播机制
  • Spring Cloud Nacos 深度解析
  • Spring Cloud OpenFeign 深度解析
  • Spring Cloud Gateway 底层原理
  • Spring Cloud Seata 深度解析
  • Spring Cloud Sentinel 深度解析
  • 《Spring》笔记
Tavio
2024-06-08
目录

Spring Boot 自动配置

# SpringBoot 自动配置深度拆解:原理、流程与实战

SpringBoot的核心优势之一便是“自动配置”,它通过“约定优于配置”的思想,帮开发者省去了传统Spring项目中繁琐的XML配置和JavaConfig配置,让项目快速启动并运行。但自动配置并非“黑魔法”,其底层是Spring框架的SPI机制、条件注解、BeanDefinition注册等技术的协同作用。

# 一、核心认知:SpringBoot自动配置是什么?

在传统Spring项目中,我们需要手动配置大量组件:比如配置数据源(DataSource)、事务管理器(TransactionManager)、视图解析器(ViewResolver)等,无论是XML文件还是JavaConfig(@Configuration + @Bean),都需要开发者逐一编写。

SpringBoot自动配置的核心目标是:根据项目依赖(pom.xml中的依赖)和配置文件(application.yml/properties),自动向Spring容器中注册符合场景需求的Bean,无需开发者手动配置。

举个例子:当项目中引入了spring-boot-starter-data-jpa依赖时,SpringBoot会自动检测到JPA相关的类,进而自动配置数据源(DataSource)、实体管理器工厂(EntityManagerFactory)、事务管理器(JpaTransactionManager)等Bean,开发者只需在配置文件中指定数据库连接信息(spring.datasource.url等)即可。

核心思想:约定优于配置。SpringBoot定义了一套默认的配置约定(如依赖坐标、配置项前缀、Bean的默认名称等),只要遵循约定,就能实现“零配置启动”。

# 二、底层基石:自动配置依赖的核心技术

SpringBoot自动配置并非凭空产生,而是基于Spring框架的核心技术扩展而来。理解这些底层技术,是搞懂自动配置的关键。

# 2.1 Spring的JavaConfig与Bean注册机制

传统Spring通过XML的<bean>标签定义Bean,而Spring 3.0+引入了JavaConfig:通过@Configuration注解标识配置类,通过@Bean注解定义Bean,Spring容器会扫描这些注解并将对应的对象注册为Bean。

SpringBoot自动配置的本质,就是通过“自动生成JavaConfig配置类”的方式,向容器中注册Bean——只不过这些配置类不是开发者写的,而是SpringBoot通过代码动态生成或预定义的。

# 2.2 Spring的条件注解(Conditional)

自动配置的核心是“按需配置”:只在特定条件满足时,才向容器中注册某个Bean。这一功能依赖于Spring的@Conditional注解。

@Conditional注解可以标记在类或方法上,用于判断是否需要创建对应的Bean。它接收一个“条件判断类”(实现Condition接口),通过重写matches()方法返回布尔值:返回true则创建Bean,返回false则不创建。

SpringBoot在@Conditional基础上,扩展了一系列更易用的“场景化条件注解”(核心在spring-boot-autoconfigure包中),比如:

  • @ConditionalOnClass:当类路径中存在指定类时,条件成立;
  • @ConditionalOnMissingClass:当类路径中不存在指定类时,条件成立;
  • @ConditionalOnBean:当容器中存在指定Bean时,条件成立;
  • @ConditionalOnMissingBean:当容器中不存在指定Bean时,条件成立(最常用,用于“默认Bean”的配置);
  • @ConditionalOnProperty:当配置文件中存在指定配置项,且值符合预期时,条件成立;
  • @ConditionalOnWebApplication:当项目是Web项目时,条件成立;
  • @ConditionalOnResource:当指定资源存在时,条件成立。

# 2.3 Spring的SPI机制(Service Provider Interface)

SPI是一种“服务发现”机制:框架定义接口,第三方实现该接口并在配置文件中声明实现类,框架通过读取配置文件加载并实例化这些实现类。

SpringBoot自动配置的“自动发现”能力,就依赖于Spring的SPI机制(具体是SpringFactoriesLoader类)。它会扫描项目中所有META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件(SpringBoot 2.7+版本,旧版本是META-INF/spring.factories),加载文件中声明的自动配置类。

# 三、核心组件:自动配置的“齿轮”如何协同?

SpringBoot自动配置的核心组件分散在spring-boot和spring-boot-autoconfigure两个核心包中,这些组件相互配合,完成“自动扫描、条件判断、Bean注册”的全流程。

# 3.1 入口注解:@SpringBootApplication

SpringBoot项目的启动类上必须添加@SpringBootApplication注解,它是自动配置的“入口开关”。但这个注解本身是一个“组合注解”,核心功能由三个注解共同实现:

// SpringBoot 3.x版本的@SpringBootApplication源码(简化)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 等同于@Configuration,标识当前类是配置类
@EnableAutoConfiguration // 核心:开启自动配置
@ComponentScan(excludeFilters = { // 组件扫描:扫描当前包及子包下的@Component等注解
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
    // 排除指定的自动配置类(核心属性,用于禁用不需要的自动配置)
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
    // ...其他属性
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

其中,@EnableAutoConfiguration是开启自动配置的核心注解,@SpringBootConfiguration让启动类具备配置类的能力,@ComponentScan负责扫描项目自身的组件。

# 3.2 核心开关:@EnableAutoConfiguration

@EnableAutoConfiguration的作用是“触发自动配置流程”,它也是一个组合注解,核心是@Import(AutoConfigurationImportSelector.class):

// @EnableAutoConfiguration源码(简化)
@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 {};
}
1
2
3
4
5
6
7
8
9
10
11
12

两个核心功能:

  1. @AutoConfigurationPackage:将启动类所在的包及子包标记为“自动配置包”,Spring会扫描该包下的@Component、@Service、@Repository等注解的类,注册为Bean;
  2. @Import(AutoConfigurationImportSelector.class):导入AutoConfigurationImportSelector类,该类是自动配置的“核心执行者”,负责加载所有符合条件的自动配置类。

# 3.3 核心执行者:AutoConfigurationImportSelector

AutoConfigurationImportSelector实现了DeferredImportSelector接口(ImportSelector的子接口),其核心功能是通过selectImports()方法加载自动配置类的全类名,然后由Spring容器创建这些类的实例。

核心流程(对应selectImports()方法):

  1. 获取自动配置的元数据(AutoConfigurationMetadata):包含自动配置类的条件信息、排序信息等;
  2. 通过getAutoConfigurationEntry()方法获取“有效的自动配置类列表”:
    • 调用getCandidateConfigurations():通过SpringFactoriesLoader扫描所有META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,获取所有候选自动配置类;
    • 去重:移除重复的自动配置类;
    • 排除:根据@EnableAutoConfiguration的exclude属性,排除指定的自动配置类;
    • 过滤:通过AutoConfigurationImportFilter过滤掉不符合条件的自动配置类(比如条件注解不满足的类)。
  3. 返回有效的自动配置类全类名数组,Spring容器会自动加载这些类。

关键源码片段(getCandidateConfigurations()方法):

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // 核心:通过SpringFactoriesLoader加载META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中的配置类
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

// 指定加载的接口类型(此处为EnableAutoConfiguration)
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    return EnableAutoConfiguration.class;
}
1
2
3
4
5
6
7
8
9
10
11
12

# 3.4 配置文件:AutoConfiguration.imports(核心约定)

SpringBoot 2.7+版本中,自动配置类的声明文件是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(旧版本是META-INF/spring.factories)。

这个文件由spring-boot-autoconfigure包提供,里面列出了所有SpringBoot预定义的自动配置类全类名,比如:

// AutoConfiguration.imports文件内容片段
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
// ...更多自动配置类
1
2
3
4
5
6
7

当项目启动时,AutoConfigurationImportSelector会扫描所有依赖包中的这个文件,加载所有候选自动配置类——这就是“自动发现”自动配置类的核心约定。

# 3.5 自动配置类:@AutoConfiguration(最终的配置载体)

AutoConfiguration.imports文件中声明的“自动配置类”,是自动配置的最终载体。这些类通常使用@AutoConfiguration注解标识(替代了旧版本的@Configuration),并结合一系列条件注解和@Bean注解,实现“按需注册Bean”。

以核心的DataSourceAutoConfiguration(数据源自动配置类)为例,其核心逻辑如下:

// DataSourceAutoConfiguration源码片段(简化)
@AutoConfiguration(after = { SqlInitializationAutoConfiguration.class }) // 自动配置类,指定加载顺序
@ConditionalOnClass(DataSource.class) // 类路径中存在DataSource类时才生效
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory") // 不存在R2DBC连接工厂时生效
@EnableConfigurationProperties(DataSourceProperties.class) // 绑定配置文件中的spring.datasource前缀配置
public class DataSourceAutoConfiguration {

    // 注册DataSourceProperties Bean:用于封装spring.datasource相关配置
    @Bean
    @ConditionalOnMissingBean
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    // 注册DataSource Bean:核心数据源Bean
    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource(DataSourceProperties properties) {
        // 基于配置文件中的信息,创建数据源(默认使用HikariCP)
        return properties.initializeDataSourceBuilder().build();
    }

    // ...其他Bean定义(如DataSourceTransactionManager)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

核心逻辑说明:

  1. @AutoConfiguration:标识该类是自动配置类,Spring会将其当作配置类处理;
  2. @ConditionalOnClass(DataSource.class):只有当项目引入了数据源相关依赖(如HikariCP、MySQL驱动),类路径中存在DataSource类时,该自动配置类才生效;
  3. @EnableConfigurationProperties(DataSourceProperties.class):将配置文件中spring.datasource前缀的配置项(如url、username、password)绑定到DataSourceProperties类的属性上;
  4. @ConditionalOnMissingBean:当容器中不存在DataSource Bean时,才会创建默认的DataSource(这意味着开发者可以通过自定义@Bean覆盖默认配置)。

# 四、完整流程:SpringBoot自动配置的“生命周期”

结合上述核心组件,我们梳理出SpringBoot自动配置的完整流程(从项目启动到自动配置完成):

# 4.1 流程拆解(共7步)

  1. 启动入口:执行启动类的main方法,调用SpringApplication.run(Application.class, args);
  2. 初始化SpringApplication:SpringApplication实例化时,会加载META-INF/spring.factories中的ApplicationContextInitializer、ApplicationListener等扩展组件;
  3. 准备环境:加载配置文件(application.yml/properties、系统环境变量、命令行参数等),创建Environment对象;
  4. 创建ApplicationContext:根据项目类型(Web/非Web)创建对应的ApplicationContext(如ServletWebServerApplicationContext);
  5. 触发自动配置:
    • ApplicationContext初始化时,会解析启动类上的@SpringBootApplication注解,进而触发@EnableAutoConfiguration;
    • @EnableAutoConfiguration导入AutoConfigurationImportSelector,其selectImports()方法通过SpringFactoriesLoader扫描所有META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,获取候选自动配置类列表;
    • 对候选自动配置类进行去重、排除(根据exclude属性)、过滤(根据条件注解),得到有效的自动配置类列表。
  6. 加载自动配置类并注册Bean:
    • Spring容器加载有效的自动配置类(如DataSourceAutoConfiguration);
    • 解析自动配置类上的条件注解,判断是否满足配置条件;
    • 若条件满足,执行自动配置类中的@Bean方法,创建对应的Bean(如DataSource、JdbcTemplate)并注册到Spring容器中。
  7. 完成自动配置:所有符合条件的Bean注册完成,ApplicationContext初始化完成,项目启动成功。

# 4.2 流程图解

graph TD
    A[启动类main方法] -- 调用 --> B[SpringApplication.run()]
    B --> C[初始化SpringApplication,加载扩展组件]
    C --> D[准备环境,加载配置文件]
    D --> E[创建ApplicationContext]
    E --> F[解析@SpringBootApplication,触发@EnableAutoConfiguration]
    F --> G[导入AutoConfigurationImportSelector]
    G --> H[扫描AutoConfiguration.imports,获取候选自动配置类]
    H --> I[去重、排除、过滤,得到有效自动配置类]
    I --> J[加载自动配置类,校验条件注解]
    J --> K{条件满足?}
    K -- 是 --> L[执行@Bean方法,注册Bean到容器]
    K -- 否 --> M[跳过该自动配置类]
    L --> N[ApplicationContext初始化完成,项目启动成功]
    M --> N
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 五、实战验证:亲手拆解自动配置的生效过程

理论终究需要实践验证。我们通过3个实战案例,亲手验证自动配置的核心机制。

# 5.1 案例1:验证DataSourceAutoConfiguration的自动生效

目标:验证“引入数据源依赖后,SpringBoot自动配置DataSource Bean”。

  1. 创建SpringBoot项目,在pom.xml中引入数据源依赖:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  2. 配置数据库信息,在application.yml中添加:
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
        username: root
        password: root
        driver-class-name: com.mysql.cj.jdbc.Driver
    
    1
    2
    3
    4
    5
    6
  3. 编写测试代码,验证容器中存在DataSource Bean:
    @SpringBootTest
    public class DataSourceAutoConfigTest {
    
        // 注入Spring容器中的DataSource Bean
        @Autowired
        private DataSource dataSource;
    
        @Test
        public void testDataSourceAutoConfig() {
            // 打印DataSource的实现类(默认是HikariDataSource)
            System.out.println("DataSource实现类:" + dataSource.getClass().getName());
            // 输出:class com.zaxxer.hikari.HikariDataSource
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  4. 执行测试:控制台打印出HikariDataSource,说明DataSourceAutoConfiguration已自动生效,成功创建了DataSource Bean。

# 5.2 案例2:验证@ConditionalOnMissingBean的覆盖机制

目标:验证“开发者自定义Bean可以覆盖自动配置的默认Bean”。

  1. 自定义DataSource Bean,创建配置类:
    @Configuration
    public class CustomDataSourceConfig {
    
        // 自定义DataSource Bean,优先级高于自动配置的Bean
        @Bean
        public DataSource customDataSource() {
            HikariConfig config = new HikariConfig();
            config.setJdbcUrl("jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC");
            config.setUsername("root");
            config.setPassword("root");
            config.setDriverClassName("com.mysql.cj.jdbc.Driver");
            // 自定义连接池参数
            config.setMaximumPoolSize(10);
            return new HikariDataSource(config);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  2. 重新执行测试:控制台打印DataSource实现类:com.zaxxer.hikari.HikariDataSource(但此时是我们自定义的实例)。若在自定义Bean上添加名称,比如@Bean("customDataSource"),通过@Qualifier("customDataSource")注入,可验证确实是自定义的Bean。
  3. 原理:DataSourceAutoConfiguration中的@ConditionalOnMissingBean表示“只有容器中没有DataSource Bean时才创建默认的”,而我们自定义的DataSource Bean先被注册到容器,因此自动配置的默认Bean不会被创建——这就是SpringBoot“自定义优先于自动配置”的核心约定。

# 5.3 案例3:验证自动配置类的排除机制

目标:验证“通过@SpringBootApplication的exclude属性排除不需要的自动配置类”。

  1. 排除DataSourceAutoConfiguration,修改启动类:
    // 排除DataSourceAutoConfiguration,禁用数据源自动配置
    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
  2. 重新执行测试:会抛出NoSuchBeanDefinitionException,提示“没有找到DataSource类型的Bean”——说明DataSourceAutoConfiguration已被成功排除,没有创建DataSource Bean。

# 六、扩展能力:自定义自动配置类

理解了自动配置的原理后,我们可以自定义自动配置类,实现“按需扩展”。比如,我们实现一个“Redis自动配置类”,当项目引入Redis依赖时,自动配置RedisTemplate Bean。

# 6.1 自定义自动配置类步骤(共5步)

  1. 引入依赖,在pom.xml中添加Redis依赖:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
    1
    2
    3
    4
  2. 创建配置属性类,绑定配置文件中的Redis配置:
    // 绑定spring.redis前缀的配置
    @ConfigurationProperties(prefix = "spring.redis")
    public class RedisProperties {
        private String host = "localhost"; // 默认值
        private int port = 6379;
        private String password;
        // getter、setter省略
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
  3. 创建自动配置类,实现RedisTemplate的自动配置:
    // 自动配置类,指定加载顺序
    @AutoConfiguration
    // 类路径中存在RedisTemplate类时生效(引入spring-boot-starter-data-redis后满足)
    @ConditionalOnClass(RedisTemplate.class)
    // 启用配置属性绑定
    @EnableConfigurationProperties(RedisProperties.class)
    public class RedisAutoConfiguration {
    
        // 自动配置RedisTemplate Bean
        @Bean
        @ConditionalOnMissingBean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(connectionFactory);
            // 配置序列化器(避免默认序列化乱码)
            Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
            jsonSerializer.setObjectMapper(objectMapper);
            
            template.setValueSerializer(jsonSerializer);
            template.setKeySerializer(new StringRedisSerializer());
            template.afterPropertiesSet();
            return template;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
  4. 声明自动配置类,创建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,添加自定义自动配置类的全类名:
    com.example.autoconfig.RedisAutoConfiguration
    
    1
  5. 测试验证:
    • 在application.yml中添加Redis配置:spring.redis.host=127.0.0.1;
    • 编写测试类,注入RedisTemplate并操作Redis:
      @SpringBootTest
      public class RedisAutoConfigTest {
      
          @Autowired
          private RedisTemplate<String, Object> redisTemplate;
      
          @Test
          public void testRedisSet() {
              redisTemplate.opsForValue().set("test:key", "hello auto config");
              String value = (String) redisTemplate.opsForValue().get("test:key");
              System.out.println("Redis value:" + value); // 输出:hello auto config
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13

至此,我们的自定义自动配置类已生效——当项目引入Redis依赖时,自动配置RedisTemplate Bean,完全遵循SpringBoot自动配置的约定。

# 七、常见问题:自动配置踩坑指南

在实际开发中,自动配置可能会出现“不生效”“Bean冲突”等问题。以下是常见问题及解决方案:

# 7.1 问题1:自动配置类不生效

现象:引入了相关依赖,但容器中没有对应的Bean(如引入spring-boot-starter-data-redis后,没有RedisTemplate Bean)。

解决方案:

  • 检查依赖是否正确引入:确认pom.xml中依赖的groupId、artifactId、版本是否正确;
  • 检查条件注解是否满足:比如@ConditionalOnClass对应的类是否存在(可能是依赖缺失或版本不兼容);
  • 检查是否被排除:确认启动类的@SpringBootApplication是否误排除了对应的自动配置类;
  • 开启 debug 日志:在application.yml中添加debug: true,启动后控制台会打印“自动配置报告”,可查看哪些自动配置类生效、哪些被排除及原因。

# 7.2 问题2:自定义Bean与自动配置Bean冲突

现象:启动时抛出NoUniqueBeanDefinitionException,提示存在多个同类型的Bean。

解决方案:

  • 使用@ConditionalOnMissingBean:在自定义Bean上添加该注解,确保只有自动配置Bean不存在时才创建自定义Bean;
  • 指定Bean名称:通过@Bean("customBeanName")给自定义Bean指定唯一名称,注入时使用@Qualifier("customBeanName")指定名称;
  • 排除自动配置类:若不需要自动配置的Bean,通过@SpringBootApplication(exclude=xxx.class)排除对应的自动配置类。

# 7.3 问题3:配置文件中的配置项不生效

现象:在application.yml中配置了spring.datasource.url等属性,但自动配置的Bean没有使用这些配置。

解决方案:

  • 检查配置项前缀是否正确:比如Redis配置的前缀是spring.redis,数据源是spring.datasource,前缀错误会导致绑定失败;
  • 检查是否启用了配置绑定:自动配置类是否添加了@EnableConfigurationProperties注解;
  • 检查属性名称是否正确:配置项名称需与@ConfigurationProperties类的属性名一致(支持驼峰命名转换,如spring.redis.maxTotal对应属性maxTotal)。

# 八、总结:自动配置的核心本质

SpringBoot自动配置的核心本质是:基于Spring的SPI机制,通过约定(AutoConfiguration.imports文件)发现自动配置类,结合条件注解实现“按需注册Bean”,最终达到“零配置启动项目”的目标。

关键要点回顾:

  1. 入口是@SpringBootApplication,核心开关是@EnableAutoConfiguration;
  2. 核心执行者是AutoConfigurationImportSelector,负责加载自动配置类;
  3. 核心约定是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件;
  4. 核心机制是“条件注解”(按需配置)和“自定义优先”(开发者自定义Bean覆盖自动配置Bean);
  5. 调试核心是开启debug: true,查看自动配置报告。
编辑 (opens new window)
#Spring Boot 自动配置
上次更新: 2026/01/21, 19:29:14
Spring Boot Bean 生命周期

Spring Boot Bean 生命周期→

最近更新
01
订单超时取消
01-21
02
双 Token 登录
01-21
03
长短链接跳转
01-21
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式