CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Spring Boot 实战入门/课时/Starter 与自动配置
RawBlame
课时目录16 节

Spring Boot 实战入门

  1. 01Spring Boot 是什么
  2. 02Starter 与自动配置
  3. 03配置与 Profile
  4. 04IoC 与依赖注入
  5. 05Bean 作用域与生命周期
  6. 06Spring AOP 入门
  7. 07Spring MVC 与 REST
  8. 08参数校验与异常处理
  9. 09JDBC 与 MyBatis
  10. 10Spring Data JPA 入门
  11. 11事务管理
  12. 12Spring Security 基础
  13. 13JWT 与 API 鉴权
  14. 14单元测试与 MockMvc
  15. 15Actuator 与健康检查
  16. 16综合练习与进阶路线

Starter 与自动配置

starter-web、starter-jdbc;@SpringBootApplication 做了什么。

30 分钟

Starter 与自动配置

这一课你将能做到

  1. 用依赖树命令看清一个 starter 背后到底引入了哪些库
  2. 打开条件评估报告,读懂哪些自动配置生效了、哪些被跳过了、为什么
  3. 亲手写一个带条件装配的自动配置类,并用 exclude 关掉官方自动配置

为什么要学

上一课你加了一个 spring-boot-starter-web,应用就具备了完整的 Web 能力。但面试官问「自动配置的原理是什么」,很多人答不上来;实际工作中「为什么我的 Redis 没连上」「为什么这个 Bean 没配进去」,十有八九也是自动配置没按你预期生效。

人话:Starter 是「依赖打包快递」,自动配置是「开箱即用的说明书执行器」。快递里有什么、说明书按什么规则执行,这一课全部拆开看。看懂之后,你会发现 Boot 的「魔法」其实全是「条件判断」。

先建立图像

你引入 starter-web
   ↓(Maven 依赖传递)
拉进 spring-web、jackson、内嵌 tomcat 等一堆 jar
   ↓(类路径上出现了这些 jar 的类)
自动配置阶段:Boot 逐条检查配置清单
   ↓
「类路径有 DispatcherServlet 相关类?→ 帮你注册 MVC 的 Bean」
「类路径没有 Redis 相关类?→ Redis 自动配置跳过,不装」

关键句:自动配置 = 拿着「条件注解」对着类路径逐条打勾。类路径上有什么,就装配什么;你没有的东西,它一个字节都不多配。

名词人话
Starter一个空壳 jar,里面没有代码,只有 pom 依赖清单
自动配置类一堆 @Bean 方法的配置类,靠条件注解决定装不装
条件注解@ConditionalOnClass(有这个类才装)、@ConditionalOnMissingBean(你没自己配我才装)等
配置清单META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,列出所有候选自动配置类

跟着做

步骤 1:用依赖树看清 starter 里有什么

在上一课的 taskflow 项目根目录执行:

mvnw dependency:tree -Dincludes=org.springframework.boot

输出节选(层级表示依赖传递):

com.example:taskflow:jar:0.0.1-SNAPSHOT
+- org.springframework.boot:spring-boot-starter-web:jar:3.3.5
|  +- org.springframework.boot:spring-boot-starter:jar:3.3.5
|  |  +- org.springframework.boot:spring-boot-starter-logging:jar:3.3.5
|  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:3.3.5
|  +- org.springframework.boot:spring-boot-starter-json:jar:3.3.5
|  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.17.2
|  +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.3.5

看到了吗:一个 starter-web 传递引入了 autoconfigure(自动配置引擎)、starter-json(Jackson)、starter-tomcat(内嵌服务器)、starter-logging(Logback 日志)。

Starter 自己没有一行 Java 代码,它只是 pom 清单。

步骤 2:常用 Starter 一览

Starter给你什么什么时候用
spring-boot-starter-webMVC + JSON + 内嵌 Tomcat写 REST API
spring-boot-starter-validationHibernate Validator 参数校验接口入参校验(本轨第 8 课)
spring-boot-starter-jdbcDataSource + JdbcTemplate轻量数据库访问(第 9 课)
spring-boot-starter-data-jpaHibernate + Spring Data JPAORM 开发(第 10 课)
spring-boot-starter-aopAspectJ 注解 + 动态代理日志、事务等横切逻辑(第 6 课)
spring-boot-starter-security安全过滤器链认证授权(第 12 课)
spring-boot-starter-actuator健康检查与监控端点运维监控(第 15 课)
spring-boot-starter-testJUnit 5 + Mockito + MockMvc测试(第 14 课)

命名规律:官方 starter 都叫 spring-boot-starter-xxx;第三方的一般叫 xxx-spring-boot-starter(如 mybatis-spring-boot-starter)。

步骤 3:打开条件评估报告,亲眼看看自动配置

在 application.yml 加一行(或启动时加参数 --debug):

debug: true

重启应用,控制台会出现一大段 CONDITIONS EVALUATION REPORT。节选:

Positive matches:
-----------------
   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class
        'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
      - found 'session' scope (OnWebApplicationCondition)

Negative matches:
-----------------
   RedisAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class
           'org.springframework.data.redis.core.RedisOperations' (OnClassCondition)

逐行翻译:MVC 自动配置「命中」了,因为类路径上找到了 DispatcherServlet 类;Redis 自动配置「没命中」,因为你没引 Redis 的依赖。这份报告就是排查「某个功能没自动生效」的第一现场——本站后端排查数据源、缓存类问题时也这么看。

看完把 debug: true 删掉(它会刷屏且拖慢启动)。

步骤 4:亲手写一个「条件装配」自动配置类

新建 greeting/GreetingProperties.java:

package com.example.taskflow.greeting;

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

@ConfigurationProperties(prefix = "greeting")
public record GreetingProperties(String prefix, String suffix) {
    public GreetingProperties {
        if (prefix == null) prefix = "Hello";
        if (suffix == null) suffix = "!";
    }
}

新建 greeting/GreetingService.java:

package com.example.taskflow.greeting;

public class GreetingService {

    private final GreetingProperties properties;

    public GreetingService(GreetingProperties properties) {
        this.properties = properties;
    }

    public String greet(String name) {
        return properties.prefix() + "," + name + properties.suffix();
    }
}

新建 greeting/GreetingAutoConfiguration.java:

package com.example.taskflow.greeting;

import org.springframework.boot.autoconfigure.AutoConfiguration;
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
@EnableConfigurationProperties(GreetingProperties.class)
@ConditionalOnProperty(prefix = "greeting", name = "enabled", havingValue = "true",
        matchIfMissing = false)
public class GreetingAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean   // 用户自己配了 GreetingService,就用用户的;没配才用我这个默认的
    public GreetingService greetingService(GreetingProperties properties) {
        return new GreetingService(properties);
    }
}

关键一步——注册到自动配置清单。新建文件 src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,内容一行:

com.example.taskflow.greeting.GreetingAutoConfiguration

然后写个临时接口验证:

package com.example.taskflow.controller;

import com.example.taskflow.greeting.GreetingService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private final GreetingService greetingService;

    public GreetingController(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    @GetMapping("/api/greet")
    public String greet() {
        return greetingService.greet("CodeForge");
    }
}

在 application.yml 打开开关:

greeting:
  enabled: true
  prefix: "你好"
  suffix: ",欢迎学习 Spring Boot"

重启访问 http://localhost:8080/api/greet,返回:你好,CodeForge,欢迎学习 Spring Boot。再把 enabled 改成 false 重启——应用直接启动失败,报 GreetingService 找不到 Bean。这就是条件装配的力量:一行配置控制一整套 Bean 的生死。

步骤 5:exclude——关掉你不想要的自动配置

最常见的例子:项目引了数据库依赖但临时想先不配数据源,启动会报「Failed to configure a DataSource」。关掉它的自动配置:

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class TaskflowApplication {
    public static void main(String[] args) {
        SpringApplication.run(TaskflowApplication.class, args);
    }
}

或在 yml 里:

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

演示完记得还原(后面数据库课程需要它)。

讲清楚要点

  1. Starter 解决「依赖地狱」:一个坐标拉齐一组库,版本由 Boot parent 仲裁。你永远不需要手动对齐 jackson、tomcat、logback 的版本。
  2. 自动配置的执行时机在用户配置之后:所以 @ConditionalOnMissingBean 语义成立——你手写的 Bean 优先级更高,Boot 的默认配置只兜底。这是「约定可覆盖」的实现基础。
  3. 条件注解是一族,不是一种:@ConditionalOnClass(类存在)、@ConditionalOnMissingBean(Bean 不存在)、@ConditionalOnProperty(配置项满足)、@ConditionalOnWebApplication(是 Web 应用)。读懂它们,自动配置源码就不神秘了。
  4. Boot 3 的清单文件变了:2.x 用 META-INF/spring.factories,3.x 改为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。看老教程时注意区分。
  5. 排查口诀:「功能没生效」先看三样——依赖在不在(依赖树)、条件满足没(评估报告)、是不是被你自己的 Bean 顶掉了(搜索同名 Bean)。

你可能会懵的地方

  • 自动配置类这么多,启动不会很慢吗? 有一百多个候选,但绝大多数在条件检查阶段就被快速跳过(只是判断类存不存在,开销极小),真正创建 Bean 的只有命中的几十个。用 --debug 报告能看到正/负匹配的完整清单。

  • 为什么我引入了依赖,对应的自动配置还是没生效? 三个检查点:①依赖真的进类路径了吗(dependency:tree 确认);②条件注解要求的类/配置满足了吗(--debug 报告 Negative matches);③是不是你的 exclude 或别人的 Bean 挡掉了。

  • @AutoConfiguration 和 @Configuration 有什么区别? @AutoConfiguration 是 @Configuration(proxyBeanMethods = false) 的特化,并表明该类要注册进自动配置清单,在所有用户配置处理完之后才执行。

  • 同一个类既在 @ComponentScan 扫描范围内又写在清单里会怎样? 组件扫描先执行,自动配置阶段的 @ConditionalOnMissingBean 会发现 Bean 已存在而跳过,最终只有一个实例,不会冲突——但不要这么写,语义混乱。

  • 面试让我说「自动配置原理」,按什么顺序讲? 入口 @EnableAutoConfiguration → 通过 Import 机制读取 AutoConfiguration.imports 清单拿到全部候选类 → 逐个用 @Conditional* 过滤(对照类路径、配置、已有 Bean)→ 命中的配置类中的 @Bean 注入容器 → 用户自定义 Bean 因先于自动配置而优先。一套话术覆盖八成考点。

错法对照

错法问题正解
手动引入 spring-webmvc、tomcat 等十几个依赖拼 Web 环境版本不齐,运行期诡异冲突引 starter-web,一个坐标搞定
清单文件放错路径(如 META-INF 下随便建)自动配置类根本不被读取必须是 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
在自动配置 Bean 上不加 @ConditionalOnMissingBean用户自定义 Bean 时报重复定义冲突默认兜底 Bean 一律加条件注解
用 exclude 关闭自动配置但还留着依赖功能静默失效,排查半天关配置就连依赖一起移除,保持一致
把业务 @Service 类也注册进自动配置清单扫描和自动配置双通道,语义混乱自动配置清单只放「基础设施」配置类

卡点急救

  1. Failed to configure a DataSource:引了 JDBC/JPA 依赖但没配数据源。要么补 spring.datasource 配置,要么 exclude = DataSourceAutoConfiguration.class(开发期临时方案)。
  2. 不知道某个 Bean 是谁配的:IDEA 里按两次 Shift 搜类名 → 打开对应的 *AutoConfiguration 源码,看它的 @Conditional* 注解即可还原条件。
  3. GreetingService 启动报 NoSuchBeanDefinitionException:按步骤 4 检查三件事——greeting.enabled=true 写了没、清单文件路径和内容对不对、类上 @ConditionalOnProperty 的 matchIfMissing 是 false(没写配置就不装)。

面试常问

  • Spring Boot 自动配置的实现原理? 见「你可能会懵的地方」最后一条的话术,核心链路:@EnableAutoConfiguration → AutoConfigurationImportSelector → 读取 imports 清单 → @Conditional 条件过滤 → 按 Bean 覆盖规则注入。

  • 如何自定义一个 Starter? 建 autoconfigure 模块(写配置属性类 + 自动配置类 + 条件注解)+ 建 starter 模块(空 pom 聚合依赖);在 autoconfigure 模块 resources 下注册 imports 清单;发布后业务方引 starter + 写配置即可用。

  • @ConditionalOnMissingBean 为什么能保证用户配置优先? 自动配置类的处理时机晚于用户 @ComponentScan/@Configuration;条件检查时用户 Bean 已注册,MissingBean 条件不满足,Boot 默认 Bean 不创建。

  • Starter 和普通依赖有什么区别? 普通依赖只提供 jar;starter = 依赖聚合(坐标组合)+ 自动配置激活(连带 autoconfigure 模块的条件装配),是「能力包」而不是「库」。

自测三问

  1. starter-web 引入后,传递带进了哪些核心库?各自负责什么?
  2. @ConditionalOnClass 和 @ConditionalOnMissingBean 分别在什么时机、检查什么?
  3. Boot 3.x 的自动配置清单文件完整路径是什么?和 2.x 有什么变化?

小结一句话

Starter 用一个坐标打包一组依赖,自动配置拿着条件注解对着类路径按需装配——「魔法」的真相是「依赖驱动 + 条件判断」。

延伸

  • Spring Boot 官方文档:Auto-configuration
  • 如何编写自定义 Starter(官方 How-to)
  • 下一课:配置与 Profile——application.yml 的完整玩法和多环境切换。
加载本节练习…
← 上一课Spring Boot 是什么下一课 →配置与 Profile