文档站点
Skip to content

自动配置(对比 Service Provider) ​

Laravel 的每个功能通过 ServiceProvider 显式注册;Spring Boot 则发明了 「自动配置」(Auto-configuration):只要 classpath 里有某个依赖,Spring Boot 就自动帮你把这个功能的 Bean 装配好。这就是「Boot」二字的含义 —— 你只管依赖,配置它来搞定。

从 spring-boot-starter-web 看自动配置 ​

你引入 spring-boot-starter-web 之后,什么都没配置,Tomcat 就启动、Spring MVC 就能用、JSON 序列化就好使。这些是谁干的?

Spring Boot 在 spring-boot-autoconfigure 包里,对常见的「功能场景」各自准备了一个「自动配置类」。以 Web 为例,它自动做了:

功能自动配置类帮你做的事Laravel 需要手动做的
内嵌 Tomcat启动 Tomcat配 Nginx/PHP-FPM
JSON 序列化自动发现 classpath 里的 Jackson手动引入依赖
静态资源把 /static/ 映射为 / 可访问放 public/ 目录即可
错误页默认错误 JSON手动写 404 页
消息转换根据 Content-Type 自动选择转换器手动处理

为什么能自动:条件装配 @ConditionalOnXxx ​

自动配置不是「无脑全部开启」,而是「满足条件才开启」。靠的是 @ConditionalOnXxx 系列注解,常见的有:

注解条件场景
@ConditionalOnClassclasspath 里有某个类有 H2 依赖才配置 H2
@ConditionalOnMissingBean容器里还没有某个 Bean用户自定义了就不覆盖
@ConditionalOnProperty某个配置项的值spring.jpa.hibernate.ddl-auto 有值才生效
@ConditionalOnWebApplication是 Web 应用非 Web 应用不加载 Web 配置

这就是自动配置「智能」的来源:它给了你覆盖的机会。你自定义了一个 DataSource Bean,Spring 就通过 @ConditionalOnMissingBean 跳过默认的。

一句话总结

自动配置 = 内置了一堆「如果没被用户自定义就自动装配」的默认 Bean。它不是魔法,是条件判断 + 约定。

自动配置的三大「开关」 ​

1. 主开关 @SpringBootApplication ​

这个注解 = 三个注解的合体:

组成注解作用
@SpringBootConfiguration标记这是配置类
@EnableAutoConfiguration开启自动配置(灵魂)
@ComponentScan扫描当前包及其子包的 @Component 等

对应到 Laravel:@ComponentScan 约等于「自动加载 app/ 目录下的类」,@EnableAutoConfiguration 约等于「自动注册所有 ServiceProvider」的开关。

2. 排除某个自动配置 ​

某个功能自动装配和你想要的不一致时,可以排除:

java
@SpringBootApplication(exclude = {
    org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class
})
public class DemoApplication { ... }

或者在配置里:

yaml
spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

3. 调试开关 ​

想知道哪些自动配置生效了/没生效:

yaml
debug: true

启动日志会打印一份「Positive matches / Negative matches」报告,非常有用。

自己写一个自动配置(理解原理) ​

把流程走一遍你就彻底懂了。假设做一个小工具包:graceful-request-id,给每个请求分配一个 ID。

第 1 步:写配置属性类 ​

java
@ConfigurationProperties(prefix = "graceful")
@Data
public class GracefulProperties {
    private boolean enabled = true;
    private String headerName = "X-Request-Id";
}

第 2 步:写自动配置类 ​

java
@AutoConfiguration
@EnableConfigurationProperties(GracefulProperties.class)
@ConditionalOnWebApplication
public class GracefulAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "graceful", name = "enabled", havingValue = "true", matchIfMissing = true)
    public RequestIdFilter requestIdFilter(GracefulProperties props) {
        return new RequestIdFilter(props);
    }
}

第 3 步:注册进 META-INF/spring/...AutoConfiguration.imports ​

在 src/main/resources/META-INF/spring/ 下建文件:

org.springframework.boot.autoconfigure.AutoConfiguration.imports

内容一行:

com.example.graceful.GracefulAutoConfiguration

然后任何项目引入你这个 jar,只要条件满足,就自动获得请求 ID 功能。

类比 Laravel 包开发

Laravel 包在 composer.json 的 extra.laravel.providers 里注册 ServiceProvider;Spring Boot 包在这个 .imports 文件里注册自动配置类。位置不同,思想一样:让使用方零配置。

自动配置与 ServiceProvider 的对比 ​

维度Laravel ServiceProviderSpring Boot 自动配置
触发时机显式注册后加载依赖在 classpath 中自动加载
是否条件化基本不大量 @ConditionalOnXxx
覆盖方式改绑定的实现自定义 Bean 即覆盖(@ConditionalOnMissingBean)
心智负担手动,清晰自动,隐藏,但可查可排

两个坑

  1. 入口类位置:@SpringBootApplication 的扫描范围是「所在包及子包」。组件放错包 → 扫不到 → 启动报错或注入 null。
  2. 依赖冲突:自动配置依赖 classpath 判断,重复引入不同版本 starter 可能出现诡异行为。用 IDEA 的 Maven 面板查看依赖树排查。

查看实际生效的配置 ​

  1. debug: true 看 Positive/Negative matches 报告
  2. 启动日志搜 Started DemoApplication 前的那段 Auto-configuration report
  3. 加 spring-boot-starter-actuator 后访问 /actuator/conditions 实时查看

理解完自动配置,你就真正理解了「Spring Boot 为什么能少写那么多配置」。接下来,搞懂这一切的语法基础:注解机制:为什么用注解。

面向 PHP / Laravel 开发者的 Spring Boot 中文文档