程云来 / 杭州
Back to Blog·Spring
·About 4 min

Spring(五):自动配置不是魔法,而是一组条件判断

把 IoC、生命周期、代理和扩展点放回 Spring Boot,理解 starter、条件装配和外部配置背后的工程取舍。


为什么 Spring Boot 看起来像“什么都准备好了”

在一个 Web 项目中加入数据库驱动和 starter,应用往往就能启动。开发者没有逐个声明数据源、事务管理器和 MVC 组件,Spring Boot 却把它们组装出来了。

这不是容器跳过了创建过程,而是把大量通用组装代码做成了条件配置:类路径上有什么依赖、配置文件写了什么、容器里是否已经存在某个 Bean,都会影响最终结果。

自动配置可以拆成三步

以数据源为例,自动配置的思路可以简化为:

text
发现相关依赖
    ↓
检查条件:是否存在 DataSource 类?是否已有用户 Bean?
    ↓
条件满足时注册默认 DataSource

用代码表示这种思想:

java
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
class DataSourceAutoConfiguration {
    @Bean
    DataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().build();
    }
}

真实实现比这个示例复杂,但判断关系是一致的:默认配置只在条件满足且用户没有提供替代实现时生效。

默认值和显式配置如何共存

自动配置的关键不是“替你做决定”,而是提供一套可被覆盖的默认值:

  1. 没有相关依赖时,不装配对应功能;
  2. 有依赖但没有自定义 Bean 时,使用默认实现;
  3. 用户提供同类型 Bean 时,让显式配置优先;
  4. 用户通过外部配置修改连接地址、超时和池大小。

因此,排查 Boot 行为时,不要只看启动类。应该同时检查依赖、条件评估报告、配置文件和容器中的实际 Bean。

正在绘制图表…
查看 Mermaid 源码
flowchart TD
    dependency[类路径依赖] --> condition[条件评估]
    config[外部配置] --> condition
    existing[用户已定义 Bean] --> condition
    condition -->|满足| default[注册默认 Bean]
    condition -->|不满足| skip[跳过自动配置]

Mermaid 大图

可滚动查看图表,点击缩放比例可恢复 100%。按 Esc 关闭。

“约定优于配置”不是不需要配置

约定减少的是重复决策,不是取消所有决策。端口、数据库地址、线程池大小和超时仍然属于运行环境,应该通过配置注入,而不是写死在代码里。

yaml
spring:
  datasource:
    url: jdbc:postgresql://localhost/orders
    hikari:
      maximum-pool-size: 10

配置外置后,同一份业务代码可以在本地、测试和生产环境使用不同参数。配置本身也需要权限、校验和可观测性,不能把所有问题都归咎于“Boot 自动完成了”。

什么时候应该绕开自动配置

自动配置适合常见路径。遇到下面情况,显式配置往往更清楚:

  1. 同时连接多个数据库,需要多个数据源和事务管理器;
  2. 默认线程池、序列化规则或安全策略不符合业务约束;
  3. 需要精确控制 Bean 的生命周期和启动顺序;
  4. 框架条件判断与项目实际边界不一致。

学习 Boot 源码时,可以从一个 starter 反向追踪:依赖带来了哪些自动配置类?每个类的条件是什么?最终注册了哪些 Bean?哪些配置可以覆盖它?

把五篇文章串起来

创建订单这条流程中,Spring 的思想可以还原成一条链:

text
接口与构造器注入
    ↓
容器创建并管理对象
    ↓
代理织入事务和其他横切能力
    ↓
模板与事件提供稳定扩展点
    ↓
Boot 按条件完成默认组装

真正值得带走的不是某个注解,而是几个可以迁移到其他框架的判断:依赖是否显式、对象图是否可读、横切逻辑是否有边界、固定流程是否抽出了稳定扩展点、默认配置是否可以被验证和覆盖。

参考:Spring Boot Auto-configurationExternalized Configuration