概述
在本快速教程中,我们将了解基于项目对象模型(POM)概念的工具 Maven 如何使用 BOM 或 "物料清单"。
有关 Maven 的更多详情,请查看我们的文章《Apache Maven 教程》。
依赖性管理概念
要了解什么是 BOM 以及 BOM 的用途,我们首先需要学习一些基本概念。
什么是 Maven POM
Maven POM 是一个 XML 文件,其中包含(关于项目的)信息和配置,Maven 使用这些信息和配置来导入依赖关系并构建项目。
什么是 Maven BOM
BOM 是 Bill Of Materials(物料清单)的缩写。BOM 是一种特殊的 POM,用于控制项目依赖项的版本,并为定义和更新这些版本提供一个中心位置。
BOM 提供了为模块添加依赖关系的灵活性,而无需担心依赖关系的版本问题。
跨依赖关系
Maven 可以发现 pom.xml 中我们自己的依赖项所需的库,并自动包含它们。收集库的依赖级别数量没有限制。
当两个依赖项指向特定工程的不同版本时,就会产生冲突。Maven 会包含哪一个?
答案是 "最接近的定义"。这意味着所使用的版本将是依赖关系树中最接近我们项目的版本。这就是所谓的 "依赖调解"。
让我们通过下面的示例来了解依赖关系调解:
A -> B -> C -> D 1.4 and A -> E -> D 1.0
本例显示项目 A 依赖于 B 和 E。B 和 E 有各自的依赖关系,它们会遇到不同版本的 D 模块。在构建 A 项目时将使用 D 1.0,因为通过 E 的路径更短。
有不同的技术来确定应包含哪个版本的模块:
- 我们总是可以通过在项目的 POM 中明确声明来保证版本。例如,为了保证使用 D 1.4,我们应在 pom.xml 文件中将其明确添加为依赖项。
- 我们可以使用 "依赖关系管理 "部分来控制模块版本,本文稍后将对此进行说明。
依赖关系管理
简而言之,依赖关系管理是一种集中管理依赖关系信息的机制。
当我们有一组继承了共同父项目的项目时,我们可以将所有依赖关系信息放在一个名为 BOM 的共享 POM 文件中。
下面是一个如何编写 BOM 文件的示例:
xml
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>baeldung</groupId>
<artifactId>Baeldung-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BaelDung-BOM</name>
<description>parent pom</description>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
我们可以看到,BOM 是一个普通的 POM 文件,其中有一个依赖管理(dependencyManagement)部分,我们可以在该部分中包含模块的所有信息和版本。
使用 BOM 文件
有两种方法可以在项目中使用之前的 BOM 文件,这样我们就可以声明我们的依赖关系,而不必担心版本号问题。
我们可以从父类继承:
xml
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>baeldung</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Test</name>
<parent>
<groupId>baeldung</groupId>
<artifactId>Baeldung-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
</project>
我们可以看到,我们的项目 Test 继承了 Baeldung-BOM。
我们还可以导入 BOM。
在大型项目中,继承的方法并不有效,因为项目只能继承一个父项目。导入是另一种选择,因为我们可以根据需要导入任意数量的 BOM。
让我们看看如何将 BOM 文件导入项目 POM:
xml
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>baeldung</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Test</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>baeldung</groupId>
<artifactId>Baeldung-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
重写 BOM 依赖关系
模块版本的优先顺序是
- 在我们的项目 pom 中直接声明的模块版本
- 模块在父项目中的版本
- 考虑到导入文件的顺序,导入 pom 中的版本
- 依赖关系调解
我们可以在项目 pom 中用所需的版本明确定义模块,从而覆盖模块的版本。
如果同一个模块在两个导入的 BOM 中定义了不同的版本,那么先声明的 BOM 文件中的版本将胜出
Spring BOM
我们可能会发现,第三方库或其他 Spring 项目会拉入对旧版本的传递依赖关系。如果我们忘记明确声明直接依赖关系,就会出现意想不到的问题。
为了克服此类问题,Maven 支持 BOM 依赖性概念。
我们可以在依赖关系管理(dependencyManagement)部分导入 spring-framework-bom,以确保所有 Spring 依赖关系都处于同一版本:
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>5.3.27</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在下面的示例中,我们使用 Spring模块时无需指定版本属性:
xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependencies>
结论
在这篇短文中,我们介绍了 Maven的BOM概念,以及如何将模块信息和版本集中到一个通用的 POM 中。
简而言之,我们可以通过继承或导入来利用 BOM 的优势。
参考文档