跳到主内容
创建时间: 2026-09-16最后更新: 2026-09-16

前面的 IoC 与 Bean 章节主要处理项目自己声明的对象:组件扫描发现 HealthController 和 HealthService,配置属性扫描创建 HealthProperties。但项目没有手动创建 Tomcat、DispatcherServlet、JSON 消息转换器等对象,它们仍然能够在启动后协作。

这些框架对象主要来自 Spring Boot 自动配置。本章沿着「依赖进入 classpath → 条件配置参与判断 → Bean 注册到容器」这条路径,解释 Starter、@SpringBootApplication、条件注解、默认配置退让和诊断报告。

1. Starter 与自动配置

Starter 和自动配置经常一起出现,但不是同一个概念:

名称作用
Starter提供一组经过版本协调的依赖
自动配置根据 classpath、配置属性和现有 Bean 决定是否注册框架对象

心跳项目添加 spring-boot-starter-webmvc 后,Maven 把 Spring MVC、JSON 支持和内嵌服务器相关依赖放入 classpath。仅有这些类还不会自动组成应用,自动配置接着检查运行环境,并注册 Web 应用需要的 Bean。

starter-flow.txt
1
pom.xml 添加 spring-boot-starter-webmvc
2
-> Maven 解析并下载一组依赖
3
-> Spring Boot 在 classpath 中发现 Web MVC 类
4
-> Web 相关自动配置条件匹配
5
-> 容器注册 DispatcherServlet、消息转换器等 Bean
6
-> 内嵌服务器启动并接收请求

Starter 也不等于所有依赖都必须通过它添加。明确知道只需要一个独立库时,可以直接声明该依赖;Spring Boot Starter 的价值在于提供常见能力所需的一组协调版本,并触发相应自动配置条件。

后面加入 JDBC Starter 时会出现同一过程:依赖提供 Spring JDBC 与 HikariCP,spring.datasource.* 提供连接参数,自动配置再创建 DataSource、事务管理器和 JdbcClient 等对象。

2. 入口注解

应用入口使用的 @SpringBootApplication 组合了三个核心注解:

spring-boot-application.java
1
@SpringBootConfiguration
2
@EnableAutoConfiguration
3
@ComponentScan
4
public @interface SpringBootApplication {}

它们分别承担不同职责:

注解职责
@SpringBootConfiguration标识应用的主要配置类,本身建立在 @Configuration 上
@EnableAutoConfiguration导入符合当前环境的自动配置候选项
@ComponentScan从入口类所在包开始发现应用自己的组件

因此,「找到项目组件」与「提供框架默认组件」是两条不同路径。HealthService 因为 @Service 和组件扫描成为 Bean;DispatcherServlet 则由 Web 自动配置注册,不要求应用源码中存在同名组件类。

入口类应放在项目根包:

package-boundary.txt
1
cn.usehook.spring.Application
2
├── config
3
├── controller
4
└── health

默认组件扫描会覆盖这些子包。如果入口类被放入更深的 cn.usehook.spring.bootstrap,同级的 controller 和 health 就不再位于默认扫描范围内。可以显式配置扫描位置,但清晰的根包布局更容易维护。

3. 条件匹配

自动配置不是无条件创建所有对象。Spring Boot 提供一组条件注解,让配置只在环境满足要求时生效:

条件判断内容
@ConditionalOnClassclasspath 中是否存在指定类
@ConditionalOnMissingClassclasspath 中是否缺少指定类
@ConditionalOnBean容器中是否已经存在指定 Bean
@ConditionalOnMissingBean容器中是否还没有指定 Bean
@ConditionalOnProperty配置属性是否存在或等于指定值
@ConditionalOnWebApplication当前是否为指定类型的 Web 应用

可以把一个库提供的自动配置简化成下面的形式。它用于理解机制,不需要放进当前心跳项目:

HealthClientAutoConfiguration.java
01
@AutoConfiguration
02
@ConditionalOnClass(HealthClient.class)
03
@ConditionalOnProperty(
04
prefix = "health.client",
05
name = "enabled",
06
havingValue = "true",
07
matchIfMissing = true
08
)
09
public class HealthClientAutoConfiguration {
10
11
@Bean
12
@ConditionalOnMissingBean
13
HealthClient healthClient() {
14
return new HealthClient();
15
}
16
}

只有 HealthClient 类存在并且配置没有关闭该功能时,这个配置类才参与注册;容器已经有用户提供的 HealthClient 时,默认 Bean 又会退让。

条件检查的是应用启动时已经收集到的环境与 Bean 定义。它不是每次 HTTP 请求都会重新执行的业务判断,也不应该用来代替方法中的业务分支。

4. 配置候选项

Spring Boot 不会通过普通组件扫描寻找依赖库中的所有自动配置。提供自动配置的库会在下面的文件中列出候选类:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1
com.example.health.HealthClientAutoConfiguration

@EnableAutoConfiguration 读取这些候选项,再逐个评估条件。这样应用只需引入库,不必知道并手动导入每个内部配置类。

当前项目自己的 @Configuration、@Service 和 @RestController 仍然由组件扫描发现。两条路径最终都会产生 Bean 定义,但来源不同:

bean-definition-sources.txt
1
应用源码
2
-> @ComponentScan
3
-> @Component、@Service、@Configuration
4
5
依赖库
6
-> @EnableAutoConfiguration
7
-> AutoConfiguration.imports 中的候选配置
8
9
两者共同注册到 ApplicationContext

如果以后开发供多个项目复用的 Starter,才需要创建 @AutoConfiguration 和 imports 文件。当前单体应用中的普通配置不要仅为了模仿框架而改造成自动配置。

5. 默认配置与自定义

自动配置的目标是提供合理默认值,同时允许应用覆盖。最常见的退让条件是 @ConditionalOnMissingBean:

auto-configuration-backoff.txt
1
容器没有目标类型 Bean
2
-> 自动配置创建默认 Bean
3
4
容器已经有应用声明的目标类型 Bean
5
-> 默认自动配置退让

这不表示任意同名方法都能覆盖自动配置。条件通常检查 Bean 类型、名称或特定注解,具体规则要查看对应自动配置类和配置属性文档。

Web MVC 中,应用实现 WebMvcConfigurer 可以增加 CORS、拦截器和格式转换等配置,同时保留 Spring Boot 的 MVC 默认设置。直接使用 @EnableWebMvc 则表示应用要更全面地接管 MVC 配置,会让部分 Boot 默认行为退出,不应该把二者当成等价写法。

后面的数据库连接章节只提供 spring.datasource 属性,让 Boot 创建池化 DataSource。只有项目确实需要特殊数据源构造逻辑时,才自己声明 DataSource Bean;一旦自定义对象满足退让条件,连接池参数绑定、监控和事务配置也要重新确认是否仍按预期生效。

自动配置减少的是通用基础设施样板代码,不会替应用决定业务对象如何分层,也不会自动创建任意没有注解和配置来源的普通类。

6. 条件报告

遇到预期 Bean 没有创建或意外使用默认实现时,可以先让应用输出条件评估报告:

terminal.bash
1
./mvnw spring-boot:run -Dspring-boot.run.arguments=--debug

也可以在 JAR 启动时传入参数:

terminal.bash
1
java -jar target/spring-0.0.1-SNAPSHOT.jar --debug

报告会区分匹配与未匹配的自动配置,并说明具体条件。排查时可以按下面顺序定位:

  1. 确认需要的 Starter 或依赖确实位于运行时 classpath;
  2. 确认相关配置键名称、Profile 和最终值;
  3. 检查是否已有 Bean 让默认配置退让;
  4. 查看对应自动配置为什么匹配或未匹配;
  5. 再确认应用是否排除了某个自动配置类。

--debug 会产生较多启动日志,适合本地诊断,不必作为生产环境的永久默认值。后面的 Actuator 还会提供条件和 Bean 端点,但端点是否对外暴露需要单独控制。

到这里,项目自己的组件与 Spring Boot 提供的基础设施已经能放进同一张容器图中理解。下一篇继续学习 Spring AOP 与代理,解释框架怎样在不改写业务方法调用方式的前提下,在方法前后加入事务、监控等横切行为。