一、配置文件导入机制的变化
Spring Boot 2.x 的做法
在 2.x 中,引入其他配置文件通常依赖 spring.profiles.active 或 spring.profiles.include,外部配置则需要通过启动参数 spring.config.location 来指定。
需要特别说明的是:**Spring Boot 2.x 它默认读取的是 application.yml。bootstrap.yml 是 Spring Cloud 体系(配合 Spring Cloud 使用时)才引入的引导配置文件,用于在应用启动早期引导配置中心(如 Nacos、Consul)的地址等信息。这一点在后面的「迁移避坑指南」中还会再次强调。
Spring Boot 3.x 的做法
3.x 引入了全新的 spring.config.import 属性,可以直接在 YAML 中导入其他配置文件,甚至直接对接远程配置中心:
bash
# Spring Boot 3.x
spring:
config:
import:
- optional:file:./custom.yml
- optional:nacos:application.yml
同样的功能在 2.x 中往往需要编写额外的 Java 代码或依赖第三方 starter 的专属属性。
同样的功能在 2.x 中往往需要编写额外的 Java 代码或依赖第三方 starter 的专属属性。
二、spring.profiles 的废弃与替代方案
这是迁移时最容易踩坑的地方。
2.x 写法(3.x 中已废弃)
bash
# Spring Boot 2.x
spring:
profiles: dev
server:
port: 8081
---
spring:
profiles: prod
server:
port: 8082
3.x 正确写法
bash
# Spring Boot 3.x
spring:
config:
activate:
on-profile: dev
server:
port: 8081
---
spring:
config:
activate:
on-profile: prod
server:
port: 8082
为什么要改?
在 2.x 中,spring.profiles 这个属性名身兼多职------既用来在文档块中标记 profile,又可以通过 spring.profiles.active 来激活 profile。语义混叠导致的问题:
- 不小心写了
spring.profiles: dev,它可能不仅仅是标记,还会直接激活 dev profile - 行为不可预测,排查困难
3.x 把"标记这个配置块属于哪个 profile"和"激活哪个 profile"这两个语义彻底拆开,职责清晰,行为可预测。
3.x 把"标记这个配置块属于哪个 profile"和"激活哪个 profile"这两个语义彻底拆开,职责清晰,行为可预测。
三、属性迁移与重命名
Spring Boot 3.x 对大量属性做了重命名,采用更统一的命名规范。常见的变更:
| 2.x 属性 | 3.x 属性 |
|---|---|
spring.redis.* |
spring.data.redis.* |
management.endpoints.web.* |
部分子属性有调整 |
server.servlet.context-path |
保持不变 |
其中 Redis 配置从 spring.redis 迁移到 spring.data.redis,是因为 3.x 把 Redis 整合进了 Spring Data 的统一配置体系。
四、Jakarta EE 命名空间迁移的间接影响
虽然这不是 YAML 语法本身的变化,但 3.x 把 javax.* 全部替换为 jakarta.*(Java EE → Jakarta EE 迁移),这会影响到与包名相关的配置,尤其是使用 spring.datasource.driver-class-name 指定老驱动时可能遇到问题。
五、底层原理:为什么要做这些改动?
打个比方:Spring Boot 2.x 像一栋不断加建的老房子,走线越来越乱,有些开关你不知道控制什么。Spring Boot 3.x 是一次重新装修,把线路理顺了。具体来说有三层原因:
1. Spring Framework 6 的底层架构升级
Spring Boot 3.x 基于 Spring Framework 6,后者要求 Java 17+ 并全面拥抱 Jakarta EE 9+。Jakarta EE 把包名从 javax 改成 jakarta,所有涉及 Servlet API、JPA、Validation 等的配置项,其底层对应的类都换了包名,配置项的绑定目标自然跟着变。
2. 配置绑定机制的规范化
Spring Boot 的配置加载底层是 Environment + PropertySource 体系。
- 2.x :多文档 YAML 处理依赖
spring.profiles做分流,该属性同时参与"文档识别"和"profile 激活"两条逻辑路径,在ConfigFileApplicationListener中处理,容易产生歧义。 - 3.x :重写了配置加载逻辑,引入
ConfigDataEnvironmentContributor和ConfigDataLocationResolver体系,把"这个配置块在什么条件下生效"(on-profile)和"我要激活哪个 profile"(spring.profiles.active)彻底解耦。
3. 为云原生和配置中心做准备
spring.config.import 的引入对应的是 ConfigDataLocationResolver 这个新的 SPI 接口。第三方配置中心(Nacos、Consul 等)只需实现该接口,就能无缝接入 Spring Boot 的配置加载链路,不再需要像 2.x 时代配合 Spring Cloud 时那样通过 Bootstrap 上下文绕一圈。
六、迁移避坑指南
第一步:使用官方迁移工具
Spring 官方提供了 spring-boot-properties-migrator,在迁移阶段加入依赖:
bash
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
它会在启动时扫描配置文件,发现废弃属性时自动做临时映射并打印警告,告诉你应该改成什么。迁移完成后记得移除该依赖。
第二步:全局搜索替换 spring.profiles
在所有 YAML 文件中搜索 spring.profiles:(注意不要误伤 spring.profiles.active 和 spring.profiles.include),替换为:
bash
spring:
config:
activate:
on-profile: xxx
第三步:检查第三方配置前缀
Redis、Elasticsearch、MongoDB 等组件的配置前缀可能已变更。最可靠的方式是对照 Spring Boot 3.x 官方文档中的 application-properties 附录逐一核对。
第四步:注意 Bootstrap 配置的移除
如果使用了 Spring Cloud:
- Spring Boot 2.x 本身 :默认加载
application.yml,并不读取bootstrap.yml - Spring Cloud 体系(配合 Boot 2.x) :依赖
bootstrap.yml+spring-cloud-starter-bootstrap,通过 Bootstrap 上下文引导配置中心 - Spring Cloud 2022.x(配合 Boot 3.x) :默认不再加载
bootstrap.yml,改为使用spring.config.import引导配置中心
如果不想改,可以手动引入 spring-cloud-starter-bootstrap 恢复旧行为,但官方推荐迁移到 spring.config.import。### 第五步:确认 Java 版本
Spring Boot 3.x 要求 Java 17+,请确认项目 JDK 版本满足要求。若仍在使用 Java 8 或 11,需要先升级 JDK 再迁移。
七、总结
这些改动的本质是把 2.x 时代"能用但语义模糊"的配置体系,重构成一套职责清晰、可扩展、面向云原生的配置加载框架。迁移时用官方 migrator 工具过渡,然后逐步按照新规范调整,就能平稳完成。