Java项目依赖版本由构建工具自动解析依赖图决定,可通过dependencyManagement统一约束多模块版本、exclusions排除传递依赖、BOM管理版本等机制精准控制。

Java项目依赖版本不是靠手动改jar包决定的,而是由构建工具在解析依赖图时自动选择——你真正能控制的,只有声明的版本范围和冲突解决策略。
用 dependencyManagement 统一约束子模块版本
多模块项目里,各 pom.xml 单独写 容易不一致。把公共依赖版本提到父POM的 块里,子模块只需声明 和 ,不写 也能继承版本。
注意:这不会引入依赖,只是“约定”;子模块仍需在 中显式声明才能生效。
-
、等配置在中也有效,会被子模块继承 - Spring Boot 的
spring-boot-dependenciesBOM 就是靠这个机制统一管理数百个依赖版本 - 若子模块想覆盖父级版本,直接在自己的
里写死即可(但不推荐)
理解 mvn dependency:tree 输出中的版本来源
执行 mvn dependency:tree -Dverbose 是排查版本冲突最直接的方式。关键看每行末尾的括号内容:
立即学习“Java免费学习笔记(深入)”;
-
(omitted for duplicate):该依赖被更高优先级的同 artifactId 版本替代了 -
(omitted for conflict with X.X.X):当前路径选了 X.X.X,其他路径有不同版本但被丢弃 - 没括号的行 = 实际打进包里的版本
版本谁胜出,取决于 Maven 的“最近优先”原则:依赖路径越短,优先级越高。不是 pom 里声明顺序,也不是字母顺序。
用 或 主动切断传递依赖
第三方库常带一堆你不想要的传递依赖(比如某个日志桥接器强制拉低 SLF4J 版本)。这时不能只靠 dependencyManagement,得主动干预:
- 在引入该第三方依赖时,用
显式排除掉有问题的传递依赖 - 若你自己发的库希望下游可选依赖(如测试工具类),在自己的
pom.xml里给对应依赖加,它就不会传递给使用者true -
不会阻止依赖被其他路径引入,只是断开当前这条路径
Gradle 用户注意 platform 和 enforcedPlatform 的区别
Gradle 没有 dependencyManagement,但可用 BOM 控制版本:
-
implementation platform('org.springframework.boot:spring-boot-dependencies:3.2.0'):仅建议版本,下游仍可覆盖 -
implementation enforcedPlatform('...'):强制锁定,任何显式声明的冲突版本都会被忽略(类似 Maven 的dependencyManagement+force=true) - BOM 文件本身必须是
type=pom,否则 Gradle 无法解析其内容
真正难的是当多个 BOM 同时存在时的版本叠加逻辑——Gradle 默认取最后一个,而 Maven 是合并所有 dependencyManagement 块后按 POM 层级覆盖。这点差异经常导致跨工具构建结果不一致。










