本文目录导读:

这是一个非常标准且重要的 Java 工程实践,尤其是在 Maven 或 Gradle 构建的多模块项目中。
一句话解释:BOM(Bill of Materials,物料清单)就像一个“版本号字典”。 它只负责定义依赖的版本,但不负责引入依赖,所有子项目或使用方只需引用这个 BOM,就能保证关键依赖的版本完全一致,避免“依赖地狱”。
下面分 Maven 和 Gradle 两种主流构建工具,介绍实现方式。
Maven 方式(最经典、最普及)
Maven 通过 dependencyManagement 标签实现 BOM,通常需要创建一个专门的 POM 工程作为 BOM。
创建 BOM 模块 (e.g., my-bom)
这个模块只包含 POM 文件,没有 Java 代码,它的作用是统一定义版本。
<!-- my-bom/pom.xml -->
<project>
<groupId>com.example</groupId>
<artifactId>my-bom</artifactId>
<version>1.0.0</version>
<!-- 注意:打包方式必须是 pom -->
<packaging>pom</packaging>
<properties>
<!-- 将版本号抽取成属性,方便统一修改 -->
<spring.boot.version>3.2.0</spring.boot.version>
<jackson.version>2.16.0</jackson.version>
<lombok.version>1.18.30</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 自家的核心库 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-core-lib</artifactId>
<version>${project.version}</version> <!-- 和BOM版本同步 -->
</dependency>
<!-- 管理第三方依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- 管理 Spring Boot 全家桶,也可以直接 import 其他 BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 管理 Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
关键点:
packaging是pom,并且使用dependencyManagement包裹。
子模块引用 BOM (e.g., my-service)
子模块不需要再写版本号,BOM 会自动带出。
<!-- my-service/pom.xml -->
<project>
<parent>
<!-- 如果你的项目有统一的父POM,可以继承 -->
<groupId>com.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0.0</version>
<relativePath>../my-parent/pom.xml</relativePath>
</parent>
<!-- 更推荐的方式:使用 scope=import,不依赖父POM -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 使用自家核心库,不需要写版本号 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-core-lib</artifactId>
<!-- 版本号由 BOM 提供,这里可以省略 -->
<!-- <version>1.0.0</version> -->
</dependency>
<!-- 使用 Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<!-- 不写版本 -->
</dependency>
<!-- 使用 Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!-- 不写版本 -->
</dependency>
</dependencies>
</project>
核心优势: 子模块只需要写
groupId和artifactId,版本完全由 BOM 控制,BOM 升级一次,所有子模块(只要不重写版本号)自动升级。
Gradle 方式(更现代、更灵活)
Gradle 原生支持 BOM,语法更简洁,推荐使用 platform 插件或直接 import。
定义 BOM 文件(通常是 build.gradle 或 build.gradle.kts)
// my-bom/build.gradle.kts (Gradle Kotlin DSL)
plugins {
`java-platform` // 声明这是一个平台(BOM)
`maven-publish` // 如果需要发布
}
javaPlatform {
// 允许定义依赖约束
allowDependencies()
}
dependencies {
// 定义约束:这是 BOM 的核心 API
constraints {
api("com.example:my-core-lib:1.0.0")
// 管理第三方库
api("com.fasterxml.jackson.core:jackson-databind:2.16.0")
api("org.projectlombok:lombok:1.18.30")
}
// 如果需要引入其他 BOM(如 Spring Boot)
api(platform("org.springframework.boot:spring-boot-dependencies:3.2.0"))
}
子模块使用 BOM
// my-service/build.gradle.kts
dependencies {
// 引入 BOM (使用 platform 关键字)
implementation(platform("com.example:my-bom:1.0.0"))
// 使用自家核心库 (版本由 BOM 提供)
implementation("com.example:my-core-lib")
// 使用 Jackson (版本由 BOM 提供)
implementation("com.fasterxml.jackson.core:jackson-databind")
// 使用 Lombok (版本由 BOM 提供,编译时注解处理器)
annotationProcessor("org.projectlombok:lombok")
// 如果某个子模块需要特殊覆盖版本,可以直接写版本,此时子模块的版本优先
// implementation("com.fasterxml.jackson.core:jackson-databind:2.14.0")
}
Gradle 特殊语法:
platform(...):强制使用 BOM 定义的版本。enforcedPlatform(...):强制覆盖所有版本(不推荐,容易冲突)。
为什么推荐统一管理?
- 消除版本冲突:避免 A 依赖 Jack 1.0,B 依赖 Jack 2.0,Jar 冲突。
- 简化升级:升级版本时,只需修改 BOM 文件的一个数字,所有模块自动沿用新版本。
- 团队规范:架构组或技术委员会可以发布一个“公司级 BOM”,所有人必须遵守,统一技术栈。
- 与 Spring Boot 对齐:Spring Boot 本身就是一个 BOM,你可以在自己的 BOM 中
import它,再添加公司私有库。
最佳实践与注意事项
- 不要滥用:BOM 只适合管理需要强制统一的依赖(如 JSON 库、日志门面、Spring 核心等),对于功能强大但版本敏感度低的库(如
commons-io),可以视情况而定。 - 优先级规则:
- 子模块中显式声明的版本号,优先级高于 BOM 定义的版本。
- BOM A 和 BOM B 定义了同一个库的不同版本,谁先声明谁生效(Maven 是“最先声明者优先”原则)。
- 发布:BOM 本身也是一个构件(Artifact),应该发布到私有仓库(Nexus/JFrog),并被所有子项目引用。
- 独立发布:BOM 应该作为一个独立的模块发布,版本号可以独立于业务模块,这样 BOM 升级时业务模块可以选择性升级。
| 方式 | 核心机制 | 适用场景 | 版本优先级 |
|---|---|---|---|
| Maven BOM | dependencyManagement + scope=import |
传统 Java EE 项目、微服务 | 子模块显式版本 > BOM |
| Gradle BOM | java-platform + platform() |
新项目、灵活度高的项目 | 子模块显式版本 > BOM |
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播