#问题
- 什么是 BOM
- BOM格式是什么
- 怎么在项目中使用BOM
#什么是 BOM
BOM 全称是 Bill Of Materials,译作材料清单。BOM 本身并不是一种特殊的文件格式,而是一个普通的 pom 文件,只是在这个 POM 中,我们罗列的是一个工程的所有依赖和其对应的版本。该文件一般被其它工程使用,当其它工程引用 BOM 中罗列的 jar 包时,不用显示指定具体的版本,会自动使用 BOM 对应的 jar 版本。
所以 BOM 的好处是用来管理一个工程的所有依赖版本信息。
#BOM 的格式
xmlxml折叠展开
<?xml version="1.0" encoding="UTF-8"?><project xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xmlns="<http://maven.apache.org/POM/4.0.0>" xsi:schemaLocation="<http://maven.apache.org/POM/4.0.0> <http://maven.apache.org/xsd/maven-4.0.0.xsd>"> <modelVersion>4.0.0</modelVersion> <groupId>com.vitahlin</groupId> <artifactId>janna-bom</artifactId> <!--BOM清单中不能使用revision--> <version>${bom.version}</version> <packaging>pom</packaging> <properties> <bom.version>1.0-SNAPSHOT</bom.version> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <encoding>UTF-8</encoding> <lombok.version>1.18.26</lombok.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <scope>provided</scope> </dependency> </dependencies> </dependencyManagement></project>其中的关键信息是:
<packaging>pom</packaging>打包方式是 pom 文件<dependencyManagement><dependencies>下定义的各种依赖的版本
#怎么引用 BOM
一般情况下,是在项目主 pom 中引入 BOM,比如 parent 的 pom 文件:
xmlxml折叠展开
<?xml version="1.0" encoding="UTF-8"?><project xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xmlns="<http://maven.apache.org/POM/4.0.0>" xsi:schemaLocation="<http://maven.apache.org/POM/4.0.0> <http://maven.apache.org/xsd/maven-4.0.0.xsd>"> <modelVersion>4.0.0</modelVersion> <groupId>com.vitahlin</groupId> <artifactId>janna</artifactId> <version>${revision}</version> <packaging>pom</packaging> <modules> <module>janna-basis</module> <module>janna-bom</module> </modules> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <revision>1.0-SNAPSHOT</revision> <bom.version>1.0-SNAPSHOT</bom.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>com.vitahlin</groupId> <artifactId>janna-bom</artifactId> <version>${bom.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement></project>在需要使用相关 JAR 包的 pom.xml 文件中 <dependencies></dependencies> 节点下引入依赖的 groupId 和 artifactId 即可,如:
xmlxml折叠展开
<?xml version="1.0" encoding="UTF-8"?><project xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xmlns="<http://maven.apache.org/POM/4.0.0>" xsi:schemaLocation="<http://maven.apache.org/POM/4.0.0> <http://maven.apache.org/xsd/maven-4.0.0.xsd>"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.vitahlin</groupId> <artifactId>janna</artifactId> <version>${revision}</version> </parent> <artifactId>janna-basis</artifactId> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies></project>这时候,就能发现 janna-basis 模块直接引入了 lombok 依赖,并且版本就是在 janna-bom 中定义的版本。这样设置后,如果项目要求升级 lombok 的版本,只需要在提供方升级验证兼容性,然后修改 BOM 依赖即可
如果需要使用不同于当前 bom 中所维护的 jar 包版本,则加上 <version> 覆盖即可,如:
xmlxml折叠展开
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency></dependencies>#版本冲突时的一些规则
当出现版本冲突时,具体使用哪一个版本的优先顺序是:
- 直接在当前工程中显示指定的版本
- parent 中配置的父工程使用的版本
- 在当前工程中通过
dependencyManagement引入的 BOM 清单中的版本,当引入的多个 BOM 都有对应 jar 包时,先引入的 BOM 生效 - 上述三个地方都没配置,则启用依赖调解 dependency mediation
什么是依赖调解? Dependency mediation(依赖调解)是指在多模块或多组件系统中,如何选择和解决不同版本的依赖关系。当项目或应用程序中引用了多个依赖,而这些依赖之间可能有版本冲突时,依赖调解的作用就是决定最终使用哪一个版本的依赖,以保证系统的稳定性和兼容性。
Maven 在面对版本冲突时,会选择“最近的依赖”(即根据依赖树的深度来选择),或者通过指定明确的版本来解决。 当有两个依赖路径,依赖到同一个 jar 的不同版本时,最短路径的版本生效。假设有如下依赖关系:
shellshell折叠展开
A -> B -> C -> D 1.4A -> E -> D 1.0在 Maven 中,最终会选择 D 的 1.4 版本,而不是 1.0 版本,因为 D 1.4 是通过路径 A -> B -> C -> D 1.4 被依赖的,而这个路径比 A -> E -> D 1.0 更长,所以 Maven 会选择版本较新的 D 1.4。

