Spring Boot: Spring Boot 自动配置原理

最后更新:2026-08-26

自动配置是 Spring Boot 的灵魂——它根据 classpath 上的类自动注册 Bean,让你"约定优于配置"。

1. 你将学到


2. 一个框架开发者的真实故事

(1) 痛点:每次集成都要写一堆配置

Alice 的团队要为 OrderFlow 集成一个新的支付 SDK。每次集成新组件,都要写 @Configuration 类、声明 Bean、配置属性、处理条件加载。团队成员 Bob 经常因为 Bean 冲突和循环依赖加班到深夜,光是一个 Redis 集成就配了 3 天。

(2) 自动配置的解法

Spring Boot Starter 把"集成一个组件"简化为"加一个依赖":

XML
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

加了这个依赖后,Redis 连接工厂、RedisTemplate 全部自动配置好。

(3) 收益

Alice 创建了 OrderFlow 自定义 Starter 后,新成员集成支付 SDK 只需加一个依赖,不再需要手动配置任何 Bean,集成时间从 3 天降到 30 分钟。


3. 自动配置加载机制

(1) 从 @EnableAutoConfiguration 到 AutoConfiguration.imports

100%
flowchart LR
    A["@EnableAutoConfiguration"] --> B["Import<br/>AutoConfigurationImportSelector"]
    B --> C["Read<br/>META-INF/spring/<br/>AutoConfiguration.imports"]
    C --> D["Filter via<br/>@Conditional<br/>Annotations"]
    D --> E["Register<br/>Qualified<br/>Auto-Configuration Classes"]
版本 加载文件 格式
Spring Boot 2.x META-INF/spring.factories key=class1,class2
Spring Boot 3.x META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 每行一个全限定类名
📌 重点: Spring Boot 3.x 使用新的 AutoConfiguration.imports 文件,不再使用 spring.factories 注册自动配置。

(2) 自动配置类的本质

自动配置类就是带条件注解的 @Configuration 类:

▶ 示例: DataSource 自动配置源码简化

JAVA
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Bean
    @ConfigurationProperties("spring.datasource")
    public DataSource dataSource(DataSourceProperties properties) {
        return DataSourceBuilder.create()
            .url(properties.getUrl())
            .username(properties.getUsername())
            .password(properties.getPassword())
            .build();
    }
}

输出:

TEXT 📖 仅展示
// 执行成功

4. 条件注解详解

(1) 核心条件注解

注解 条件 典型用途
@ConditionalOnClass classpath 存在指定类 只有引入依赖才生效
@ConditionalOnMissingClass classpath 不存在指定类 缺少依赖时提供替代方案
@ConditionalOnBean 容器中存在指定 Bean 依赖其他 Bean 时使用
@ConditionalOnMissingBean 容器中不存在指定 Bean 提供默认 Bean,用户自定义时让路
@ConditionalOnProperty 配置属性满足条件 通过配置开关控制功能

▶ 示例: @ConditionalOnProperty 开关控制

JAVA
@Configuration
@ConditionalOnProperty(
    prefix = "orderflow.notification",
    name = "enabled",
    havingValue = "true",
    matchIfMissing = false
)
public class NotificationConfig {

    @Bean
    public NotificationService emailNotificationService() {
        return new EmailNotificationService();
    }
}

输出:

TEXT 📖 仅展示
// 执行成功
YAML
orderflow:
  notification:
    enabled: true   # Set false to disable notification

▶ 示例: @ConditionalOnMissingBean 提供默认实现

JAVA
@Configuration
public class OrderFlowAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(IdGenerator.class)
    public IdGenerator uuidIdGenerator() {
        return new UuidIdGenerator();
    }

    @Bean
    @ConditionalOnMissingBean(OrderNumberGenerator.class)
    @ConditionalOnProperty(
        prefix = "orderflow.order",
        name = "number-prefix",
        havingValue = "ORD",
        matchIfMissing = true
    )
    public OrderNumberGenerator defaultOrderNumberGenerator() {
        return new SequentialOrderNumberGenerator("ORD");
    }
}

输出:

TEXT 📖 仅展示
// 执行成功

5. 自定义 Starter

(1) Starter 命名规范

类型 命名规范 示例
官方 Starter spring-boot-starter-* spring-boot-starter-web
第三方 Starter *-spring-boot-starter orderflow-spring-boot-starter

(2) Starter 项目结构

TEXT 📖 仅展示
orderflow-spring-boot-starter/
├── src/main/
│   ├── java/com/orderflow/autoconfigure/
│   │   ├── OrderFlowAutoConfiguration.java
│   │   └── OrderFlowProperties.java
│   └── resources/
│       └── META-INF/spring/
│           └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
└── pom.xml

▶ 示例: 自定义 Starter 完整代码

JAVA
// OrderFlowProperties.java
@ConfigurationProperties(prefix = "orderflow.notification")
public record OrderFlowNotificationProperties(
    boolean enabled,
    String fromEmail,
    String templatePath
) {}

// OrderFlowAutoConfiguration.java
@AutoConfiguration
@ConditionalOnClass(JavaMailSender.class)
@ConditionalOnProperty(
    prefix = "orderflow.notification",
    name = "enabled",
    havingValue = "true"
)
@EnableConfigurationProperties(OrderFlowNotificationProperties.class)
public class OrderFlowAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(NotificationService.class)
    public NotificationService notificationService(
            OrderFlowNotificationProperties props) {
        return new EmailNotificationService(
            props.fromEmail(),
            props.templatePath()
        );
    }
}

输出:

TEXT 📖 仅展示
执行成功
TEXT 📖 仅展示
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.orderflow.autoconfigure.OrderFlowAutoConfiguration

6. 调试与排除自动配置

(1) --debug 模式

启动时加 --debug 参数,Spring Boot 输出自动配置报告:

BASH
java -jar orderflow-service.jar --debug

▶ 示例: 自动配置报告解读

TEXT 📖 仅展示
============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:
-----------------
   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required class 'javax.sql.DataSource'

Negative matches:
-----------------
   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory'

Exclusions:
-----------
   None

Unconditional classes:
----------------------
   org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration

输出:

TEXT 📖 仅展示
执行成功
报告区域 含义
Positive matches 条件满足,已生效的自动配置
Negative matches 条件不满足,未生效的自动配置
Exclusions 被显式排除的自动配置
Unconditional classes 无条件注册的自动配置

(2) 排除自动配置

▶ 示例: 排除不需要的自动配置

JAVA
// Method 1: Annotation exclusion
@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class
})
public class OrderFlowApplication { ... }

// Method 2: Configuration property
// application.yml
spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

输出:

TEXT 📖 仅展示
// 执行成功
排除方式 适用场景 灵活度
@SpringBootApplication(exclude) 永远排除 编译时确定
spring.autoconfigure.exclude 按环境排除 运行时可变
@ConditionalOnProperty 按条件排除 最灵活

7. 综合示例:OrderFlow 通知 Starter 完整实现

JAVA
// orderflow-notification-spring-boot-starter

// OrderFlowNotificationProperties.java
package com.orderflow.autoconfigure;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "orderflow.notification")
public record OrderFlowNotificationProperties(
    boolean enabled,
    String fromEmail,
    String templatePath,
    SmtpConfig smtp
) {
    public record SmtpConfig(String host, int port, boolean ssl) {}
}

// NotificationService.java
package com.orderflow.autoconfigure;

public interface NotificationService {
    void send(String to, String subject, String body);
}

// EmailNotificationService.java
package com.orderflow.autoconfigure;

public class EmailNotificationService implements NotificationService {
    private final String fromEmail;
    private final String templatePath;

    public EmailNotificationService(String fromEmail, String templatePath) {
        this.fromEmail = fromEmail;
        this.templatePath = templatePath;
    }

    @Override
    public void send(String to, String subject, String body) {
        // Email sending logic
        System.out.printf("Send to %s: [%s] %s%n", to, subject, body);
    }
}

// OrderFlowNotificationAutoConfiguration.java
package com.orderflow.autoconfigure;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
@ConditionalOnClass(name = "org.springframework.mail.javamail.JavaMailSender")
@ConditionalOnProperty(prefix = "orderflow.notification", name = "enabled", havingValue = "true")
@EnableConfigurationProperties(OrderFlowNotificationProperties.class)
public class OrderFlowNotificationAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(NotificationService.class)
    public NotificationService notificationService(OrderFlowNotificationProperties props) {
        return new EmailNotificationService(props.fromEmail(), props.templatePath());
    }
}
TEXT 📖 仅展示
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.orderflow.autoconfigure.OrderFlowNotificationAutoConfiguration

❓ 常见问题

Q 自动配置和手动配置会冲突吗?
A 不会。自动配置类大量使用 @ConditionalOnMissingBean,如果你手动定义了同类型的 Bean,自动配置会自动让路。这就是"用户定义优先"原则。
Q 为什么我的自动配置没有生效?
A 常见原因:1)classpath 缺少依赖类;2)@ConditionalOnProperty 条件不满足;3)AutoConfiguration.imports 文件路径或内容错误;4)自动配置类不在组件扫描范围内(但自动配置通过 imports 文件加载,不需要扫描)。
Q spring.factories 还能用吗?
A Spring Boot 3.x 仍然支持 spring.factories 向后兼容,但注册自动配置应优先使用 AutoConfiguration.imports 文件。spring.factories 将在未来版本移除。
Q 自定义 Starter 需要几个模块?
A 通常两个:1)autoconfigure 模块(自动配置代码);2)starter 模块(仅 pom.xml 聚合依赖)。简单项目可以合并为一个模块。
Q 如何查看当前生效了哪些自动配置?
A 1)启动加 --debug 参数查看报告;2)Actuator 的 /actuator/conditions 端点;3)在 IDE 中搜索 AutoConfiguration.imports 文件。
Q 排除自动配置有什么风险?
A 排除后相关功能不可用,依赖它的其他自动配置可能失败。确保你了解排除的影响,可以通过 debug 报告确认依赖链。

📖 小节


📝 作业

  1. 基础题(难度⭐):使用 --debug 模式启动 OrderFlow 项目,列出所有 Positive matches 中的自动配置类,理解每个自动配置依赖的 classpath 条件。

  2. 进阶题(难度⭐⭐):创建一个 orderflow-spring-boot-starter,包含 @ConditionalOnProperty 开关控制的通知功能,在 OrderFlow 项目中引入并验证。

  3. 挑战题(难度⭐⭐⭐):实现一个支持多实现的自动配置——当 classpath 有 Kafka 时使用 Kafka 通知,否则使用 Email 通知,两者都不可用时使用日志通知,思考条件注解的优先级和互斥设计。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏