首页 / Spring Boot 入门教程 / 自动配置原理

Spring Boot 入门教程

自动配置原理

本教程共 48 篇 · 第 6 篇 · 更新于 2026-08-13 · 约 4 分钟阅读

自动配置条件注解@ConditionalAutoConfiguration自定义Starter组件扫描

本节目标:搞懂 Spring Boot「零配置」的秘密——条件注解怎么工作、自动配置怎么加载、如何自定义与关闭自动配置。

自动配置:把配菜备齐的厨房

第一次用 Spring Boot,你只加了一个 spring-boot-starter-webmvc 依赖,什么都没配。启动后 Tomcat 起来了,JSON 能返回了。谁干的?自动配置(Auto-configuration)。

官方文档一句话点破:Spring Boot 根据 classpath 上的 jar 依赖,自动帮你配置 Spring 应用。比如 classpath 里有 H2 数据库驱动,你又没手动配数据源,Boot 就自动配一个内存数据库。

把自动配置想成点菜:你点了「Web」这道菜(Starter),厨房(Spring Boot)自动把配菜备齐——Tomcat、Jackson、Spring MVC,全给你端上来。

自动配置不是魔法。它由两块拼成:条件注解决定「配不配」,加载机制决定「怎么配」。

总开关:@EnableAutoConfiguration

自动配置默认关着。你要在一个 @Configuration 类上显式开启:

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
public class MyApplication {
}

实际项目里,你用的是 @SpringBootApplication。它内部就包含 @EnableAutoConfiguration(第 4 章讲过),主类一标,自动配置就开了。

Warning

全项目只能有一个 @SpringBootApplication@EnableAutoConfiguration。加在多个类上会出问题,官方建议只加在主配置类上。

条件注解:自动配置的投票器

每个自动配置类都是候选。装不装,由 @Conditional* 系列注解投票决定。这族注解是自动配置的灵魂,面试常考。

注解生效条件
@ConditionalOnClass / @ConditionalOnMissingClassclasspath 里有 / 没有某个类
@ConditionalOnBean / @ConditionalOnMissingBean容器里已经 / 还没有某个 Bean
@ConditionalOnProperty配置属性等于指定值
@ConditionalOnResource某个资源文件存在
@ConditionalOnWebApplication / @ConditionalOnNotWebApplication当前是不是 Web 应用
@ConditionalOnExpressionSpEL 表达式为 true
@Conditional自定义条件类

@ConditionalOnClass 出场率最高。只有类存在,配置才生效:

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "com.mysql.cj.jdbc.Driver")
public class MySqlAutoConfiguration {
    // classpath 里有 MySQL 驱动时,这个配置类才被加载
}

name 写全类名,类没在 classpath 上也不会编译报错,这是官方推荐写法。

@ConditionalOnProperty 按配置项开关。经典用法:同一个接口两个实现,靠一个属性切换。下面的例子摘自 mkyong 的开源示例:

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

@Service
@ConditionalOnProperty(name = "app.feature.new", havingValue = "true")
public class RedisSessionService implements WebSessionService {
    @Override
    public String getUserData() {
        return "Data from Redis...";
    }
}
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

@Service
@ConditionalOnProperty(name = "app.feature.new", havingValue = "false", matchIfMissing = true)
public class PostgreSessionService implements WebSessionService {
    @Override
    public String getUserData() {
        return "Data from PostgreSQL Database";
    }
}

application.properties 里写一行:

app.feature.new=true

属性为 true 时注册 Redis 实现;为 false 或缺失时,matchIfMissing = true 让 Postgre 实现兜底。写一个开关,两套逻辑,改配置就切换。

加载机制:谁在找自动配置类

条件注解只是「候选」。谁来收集候选?Spring Boot 启动时会扫描所有 jar 里的一个固定文件:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

这个文件每行写一个自动配置类的全类名。Boot 把 classpath 上所有 jar 的这个文件读出来,汇总成候选列表,再逐个用条件注解评估。评估通过的,它的 @Bean 方法就被执行,Bean 进容器。

Note

时间线:2.7 之前,自动配置注册在 META-INF/spring.factories;2.7 起引入上面的 .imports 文件,两者并存过渡;3.0 起只认 .imports。看到旧教程写 spring.factories,别照抄。

自动配置类本身用 @AutoConfiguration 标注。它相当于 @Configuration(proxyBeanMethods = false),还能用 afterbefore 指定顺序:

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;

@AutoConfiguration(after = DataSourceAutoConfiguration.class)
public class MyAutoConfiguration {
}

顺序很重要。JPA 的自动配置,必须等数据源配好再跑。

还有一个配套注解:@AutoConfigurationPackage。它把主类所在包登记为「自动配置包」。JPA 实体、Spring Data 仓库的默认扫描范围,就是从这个包出发的。@EnableAutoConfiguration 会自动带上它,平时不用手写。

查账:谁生效了,为什么

自动配置看着像黑盒,其实能查账。启动时加 --debug

mvn spring-boot:run -Dspring-boot.run.arguments=--debug

控制台会输出一份「条件评估报告」:每个自动配置类,生效(matched)还是没生效(not matched),为什么。没生效的原因写得很直白,比如「没找到某个类」「已有同名 Bean」。

排查「为什么我的配置没生效」,第一件事就是看这份报告。

关掉多余的自动配置

有的自动配置你不想要。比如项目不用数据库,启动却报数据源相关错误。用 exclude 关掉:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class MyApplication {
}

类不在 classpath 时,用 excludeName 写全类名。也可以用配置属性,一处顶全局。注解里的 exclude 和属性的排除是叠加关系,按并集生效:

spring.autoconfigure.exclude=org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration
Tip

排除是「局部刹车」。自动配置本身很谦让——你一旦自己定义了 DataSource Bean,Boot 的默认数据源配置会自动退让,多数情况不用排除。

自定义自动配置:三步写自己的 Starter

理解了机制,就能写自己的自动配置。给一个「问候服务」做自动配置,三步走。

第一步,服务类和属性类。服务类提供业务,属性类让用户可配置:

package com.example.hello;

public class HelloService {

    private final String prefix;

    public HelloService(String prefix) {
        this.prefix = prefix;
    }

    public String sayHello(String name) {
        return prefix + "," + name;
    }
}
package com.example.hello;

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

@ConfigurationProperties(prefix = "hello")
public class HelloProperties {

    private String prefix = "你好";

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
}

第二步,自动配置类。条件齐上:类存在、属性允许、Bean 缺失才配:

package com.example.hello;

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(HelloService.class)
@ConditionalOnProperty(prefix = "hello", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public HelloService helloService(HelloProperties properties) {
        return new HelloService(properties.getPrefix());
    }
}

第三步,注册。在 src/main/resources 下建文件:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

内容一行:

com.example.hello.HelloAutoConfiguration

用户引入这个 jar 后,在 application.yml 里写:

hello:
  prefix: "早上好"

HelloService Bean 就带着新前缀出现了。@ConditionalOnMissingBean 是关键——用户自己定义了 HelloService,你的自动配置就退让,不抢戏。这就是 Starter 的原理,第 8 章接着讲它的依赖体系。

小结

  • 自动配置 = 条件注解(配不配)+ 加载机制(怎么配)。
  • @ConditionalOnMissingBean 是「让位」机制,用户自定义优先。
  • --debug 看条件报告,exclude 关多余配置。
  • 自定义自动配置:@AutoConfiguration 类 + .imports 注册文件。