Maven 简明教程

Maven - Manage Dependencies

Maven 的核心功能之一是依赖项管理。一旦我们开始处理多模块项目(包含数百个模块/子项目),那么管理依赖项就会成为一项困难的任务。Maven 提供了高度的控制来管理此类场景。

Transitive Dependencies Discovery

通常一种情况是,一个库(例如 A)依赖于另一个库(例如 B)。如果另一个项目 C 要使用 A,那么该项目需要使用库 B。

Maven 帮助避免此类要求以发现所有必需的库。Maven 通过读取依赖项的项目文件 (pom.xml)、找出它们的依赖项等来做到这一点。

我们只需要在每个项目 pom 中定义直接依赖。Maven 会自动处理其余部分。

使用传递依赖项,包含的库的图形可能会迅速增长到很大程度。当出现重复库时,可能会出现这种情况。Maven 提供了一些功能来控制传递依赖项的范围。

Sr.No.

Feature & Description

1

Dependency mediation 确定当遇到某个构件的多个版本时要使用哪个版本的依赖项。如果两个依赖项版本在依赖项树中的深度相同,则将使用第一个声明的依赖项。

2

Dependency management 当依赖项以传递依赖项的形式出现时,直接指定要使用的构件的版本。对于一个示例项目,C 可以将其依赖项管理部分中的 B 包含为依赖项,并直接控制在引用它时要使用 B 的哪个版本。

3

Dependency scope 根据构建的当前阶段包含依赖项。

4

Excluded dependencies 可以使用“exclusion”元素排除任何传递依赖项。例如,A 依赖于 B,而 B 依赖于 C,那么 A 可以将 C 标记为已排除。

5

Optional dependencies 可以使用“optional”元素将任何传递依赖项标记为可选。例如,A 依赖于 B,而 B 依赖于 C。现在 B 将 C 标记为可选的。那么 A 不会使用 C。

Dependency Scope

可以使用各种依赖项范围来限制传递依赖项发现,如下所述。

Sr.No.

Scope & Description

1

compile 此范围表明依赖项可在项目的 classpath 中使用。它是默认范围。

2

provided 此范围表明依赖项将在运行时由 JDK 或 web 服务器/容器提供。

3

runtime 此范围表明在编译过程中不需要依赖项,但在执行过程中需要依赖项。

4

test 此范围表明依赖项仅可用于测试编译和执行阶段。

5

system 此范围表明您必须提供系统路径。

6

import 只有依赖项为 pom 类型时,才使用此范围。此范围表明应当使用该 POM 中 <dependencyManagement> 部分中的依赖项替换指定的 POM。

Dependency Management

通常,在通用项目下,我们有一组项目。在这种情况下,我们可以创建一个具有所有通用依赖项的通用 pom,然后将此 pom 设为子项目 pom 的父级。下面的示例将帮助你理解此概念。

dependency graph

以下是上述依赖项关系图的详细信息 -

  1. App-UI-WAR 依赖于 App-Core-Lib 和 App-Data-Lib。

  2. Root 是 App-Core-Lib 和 App-Data-Lib 的父级。

  3. Root 在其依赖项部分中将 Lib1、lib2、Lib3 定义为依赖项。

App-UI-WAR

<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   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.companyname.groupname</groupId>
   <artifactId>App-UI-WAR</artifactId>
   <version>1.0</version>
   <packaging>war</packaging>
   <dependencies>
      <dependency>
         <groupId>com.companyname.groupname</groupId>
         <artifactId>App-Core-lib</artifactId>
         <version>1.0</version>
      </dependency>
   </dependencies>
   <dependencies>
      <dependency>
         <groupId>com.companyname.groupname</groupId>
         <artifactId>App-Data-lib</artifactId>
         <version>1.0</version>
      </dependency>
   </dependencies>
</project>

App-Core-lib

<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
      <artifactId>Root</artifactId>
      <groupId>com.companyname.groupname</groupId>
      <version>1.0</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.companyname.groupname</groupId>
   <artifactId>App-Core-lib</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
</project>

App-Data-lib

<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
      <artifactId>Root</artifactId>
      <groupId>com.companyname.groupname</groupId>
      <version>1.0</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.companyname.groupname</groupId>
   <artifactId>App-Data-lib</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
</project>

Root

<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   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.companyname.groupname</groupId>
   <artifactId>Root</artifactId>
   <version>1.0</version>
   <packaging>pom</packaging>
   <dependencies>
      <dependency>
         <groupId>com.companyname.groupname1</groupId>
         <artifactId>Lib1</artifactId>
         <version>1.0</version>
      </dependency>
   </dependencies>
   <dependencies>
      <dependency>
         <groupId>com.companyname.groupname2</groupId>
         <artifactId>Lib2</artifactId>
         <version>2.1</version>
      </dependency>
   </dependencies>
   <dependencies>
      <dependency>
         <groupId>com.companyname.groupname3</groupId>
         <artifactId>Lib3</artifactId>
         <version>1.1</version>
      </dependency>
   </dependencies>
</project>

现在,当我们构建 App-UI-WAR 项目时,Maven 将通过遍历依赖项关系图来发现所有依赖项,并构建应用程序。

从以上示例中,我们可以了解以下关键概念 -

  1. 可以使用父级 pom 的概念将通用依赖项置于单个位置。 App-Data-libApp-Core-lib 项目的依赖项在 Root 项目中列出(请参阅 Root 的打包类型。它是 POM)。

  2. 不必在 App-UI-WAR 中将 Lib1、lib2、Lib3 指定为依赖项。Maven 使用 Transitive Dependency Mechanism 来管理此类详细信息。