Maven - 管理依赖
Maven 的核心特性之一是依赖管理。 一旦我们必须处理多模块项目(由数百个模块/子项目组成),管理依赖项是一项艰巨的任务。 Maven 提供了高度的控制来管理这些场景。
传递依赖发现
通常情况下,一个库,比如 A,依赖于另一个库,比如 B。如果另一个项目 C 想要使用 A,那么该项目也需要使用库 B。
Maven 有助于避免此类要求以发现所需的所有库。 Maven 通过读取依赖项的项目文件(pom.xml),找出它们的依赖项等等来做到这一点。
我们只需要在每个项目 pom.xml 中定义直接依赖即可。 Maven 自动处理其余部分。
通过传递依赖,包含库的图可以在很大程度上快速增长。 存在重复库时可能会出现这种情况。 Maven 提供了一些特性来控制传递依赖的程度。
序号 | 特征 & 描述 |
---|---|
1 | Dependency mediation 确定遇到工件的多个版本时要使用哪个版本的依赖项。 如果两个依赖版本在依赖树中的深度相同,则将使用第一个声明的依赖。 |
2 | Dependency management 直接指定在传递依赖中遇到工件时要使用的工件版本。 例如,项目 C 可以在其依赖项管理部分中包含 B 作为依赖项,并直接控制在引用 B 时要使用哪个版本。 |
3 | Dependency scope 根据构建的当前阶段包括依赖项。 |
4 | Excluded dependencies 可以使用"排除"元素排除任何传递依赖。 例如,A 依赖于 B,B 依赖于 C,则 A 可以将 C 标记为已排除。 |
5 | Optional dependencies 任何传递依赖都可以使用"可选"元素标记为可选。 例如,A 依赖于 B,B 依赖于 C。现在 B 将 C 标记为可选。 那么 A 不会使用 C。 |
依赖作用域
传递依赖发现可以使用各种依赖作用域来限制,如下所述。
序号 | 作用域 & 描述 |
---|---|
1 | compile 此范围表示依赖项在项目的类路径中可用。 它是默认范围。 |
2 | provided 此范围表示依赖项将由 JDK 或 web-Server/Container 在运行时提供。 |
3 | runtime 此范围表示编译不需要依赖项,但在执行期间需要依赖项。 |
4 | test 此范围表示依赖项仅可用于测试编译和执行阶段。 |
5 | system 此范围表示您必须提供系统路径。 |
6 | import 仅当依赖项是 pom 类型时才使用此范围。 此范围指示应将指定的 POM 替换为该 POM 的 <dependencyManagement> 部分中的依赖项。 |
依赖管理
通常,我们在一个普通项目下有一组项目。 在这种情况下,我们可以创建一个具有所有公共依赖项的公共 pom,然后将这个 pom 作为子项目 pom 的父级。 以下示例将帮助您理解这个概念。
以下是上述依赖图的详细信息 −
- App-UI-WAR 依赖于 App-Core-lib 和 App-Data-lib。
- Root 是 App-Core-lib 和 App-Data-lib 的父级。
- 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 会通过遍历依赖图发现所有依赖并构建应用程序。
从上面的例子中,我们可以学到以下关键概念 −
可以使用父 pom 的概念将公共依赖项放置在单个位置。 App-Data-lib 和 App-Core-lib 项目的依赖项在 Root 项目中列出(参见 Root 的打包类型。它是 POM)。
在 App-UI-WAR 中无需指定 Lib1、lib2、Lib3 作为依赖项。 Maven 使用传递依赖机制来管理这些细节。