这是用户在 2024-10-20 21:18 为 https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?


依赖机制简介


依赖管理是 Maven 的核心特性。管理单个项目的依赖项很简单。管理由数百个模块组成的模块化项目和应用程序的依赖项也是可行的。Maven 在定义、创建和维护具有明确类路径和库版本的可重复构建方面提供了很大帮助。

 了解更多关于:

 传递依赖


Maven 通过自动包含传递依赖,避免了发现和指定您自己的依赖所需的库的需要。


此功能通过读取远程仓库中指定的依赖项的项目文件来实现。一般来说,这些项目的所有依赖项都用于您的项目,以及项目从其父项目或依赖项继承的任何依赖项,依此类推。


无限制于可以收集到的依赖关系的层级数量。只有当发现循环依赖时才会出现问题。


具有传递依赖性,包含库的图可以迅速变得相当大。因此,存在一些额外功能来限制包含哪些依赖项:


  • 依赖调解 - 这决定了在遇到多个版本作为依赖时,将选择哪个版本的工件。Maven 选择“最近的定义”。也就是说,它使用与您的项目在依赖树中最接近的依赖项的版本。您可以通过在项目的 POM 文件中明确声明来始终保证版本。请注意,如果两个依赖项版本在依赖树中处于相同的深度,则第一个声明获胜。

    • "最近定义"意味着所使用的版本将是依赖树中与您的项目最接近的一个。考虑这个依赖树:
        A
        ├── B
        │   └── C
        │       └── D 2.0
        └── E
            └── D 1.0


      in 文本中,A、B 和 C 的依赖关系定义为 A -> B -> C -> D 2.0 和 A -> E -> D 1.0,然后在构建 A 时将使用 D 1.0,因为从 A 通过 E 到 D 的路径更短。您可以在 A 中显式添加对 D 2.0 的依赖,以强制使用 D 2.0,如下所示:

        A
        ├── B
        │   └── C
        │       └── D 2.0
        ├── E
        │   └── D 1.0
        │
        └── D 2.0      

  • 依赖管理 - 这允许项目作者在遇到传递依赖或未指定版本的依赖时,直接指定要使用的工件版本。在前一节的例子中,即使 A 没有直接使用该依赖,依赖也被直接添加到了 A 中。相反,A 可以在其依赖管理部分将 D 作为依赖项包含,并直接控制何时或是否使用 D 的哪个版本。

  • 依赖范围 - 这允许您仅包括适合当前构建阶段的依赖项。具体描述如下。

  • 排除的依赖项 - 如果项目 X 依赖于项目 Y,而项目 Y 又依赖于项目 Z,项目 X 的所有者可以显式排除项目 Z 作为依赖项,使用“排除”元素。

  • 可选依赖项 - 如果项目 Y 依赖于项目 Z,项目 Y 的所有者可以使用“可选”元素将项目 Z 标记为可选依赖项。当项目 X 依赖于项目 Y 时,X 将只依赖于 Y,而不是 Y 的可选依赖项 Z。项目 X 的所有者可以选择明确添加对 Z 的依赖。 (可以将可选依赖项视为“默认排除”。)


尽管传递依赖可能隐式包含所需的依赖,但明确指定源代码直接使用的依赖项是一种良好的实践。这种最佳实践在其项目依赖项发生变化时尤其显示出其价值。


例如,假设您的项目 A 指定了对另一个项目 B 的依赖,而项目 B 又指定了对项目 C 的依赖。如果您直接使用项目 C 中的组件,并且没有在项目 A 中指定项目 C,那么当项目 B 突然更新/删除对项目 C 的依赖时,可能会导致构建失败。


另一个直接指定依赖的原因是,它为你的项目提供了更好的文档:通过只阅读你的项目中的 POM 文件,或者通过执行 mvn dependency:tree,人们可以了解更多信息。


Maven 还提供了依赖:analyze 插件目标,用于分析依赖:它有助于使这一最佳实践更容易实现。

 依赖范围


依赖作用域用于限制依赖的及物性和确定何时将依赖包含在类路径中。


有 6 个范围:

  •  编译

    这是默认范围,如果没有指定则使用。编译依赖项可在项目的所有类路径中找到。此外,这些依赖项会传播到依赖的项目中。
  •  未提供源文本,请提供需要翻译的学术文本

    这与 compile 非常相似,但表示您期望 JDK 或容器在运行时提供依赖项。例如,当构建 Java 企业版(Java Enterprise Edition)的 Web 应用程序时,您会将 Servlet API 和相关 Java EE API 的依赖项设置为 provided 范围,因为 Web 容器提供了这些类。具有此范围的依赖项被添加到用于编译和测试的类路径中,但不是运行时类路径。它不具有传递性。
  •  运行时

    此范围表明依赖项不是编译所必需的,而是执行所必需的。Maven 在运行时和测试类路径中包含具有此范围的依赖项,但不在编译类路径中。
  •  测试

    此范围表明,该依赖项对于应用程序的正常使用不是必需的,仅在测试编译和执行阶段可用。此范围不具有传递性。通常,此范围用于 JUnit 和 Mockito 等测试库。它还用于 Apache Commons IO 等非测试库,如果这些库在单元测试(src/test/java)中使用,但在模型代码(src/main/java)中未使用。
  •  系统

    此范围与 provided 相似,但你必须明确提供包含它的 JAR 文件。该工件始终可用,且不在存储库中查找。
  •  导入

    此范围仅在 <dependencyManagement> 部分的类型 pom 依赖项上受支持。这表示依赖项应替换为指定 POM 的 <dependencyManagement> 部分中的有效依赖项列表。由于它们被替换,具有范围 import 的依赖项实际上并不参与限制依赖项的传递性。


每个作用域(除 import 外)以不同的方式影响传递依赖,如下表所示。如果依赖项设置为左侧列中的作用域,则该依赖项与顶部行作用域的传递依赖导致主项目中交叉处列出的作用域的依赖项。如果没有列出作用域,则表示省略了该依赖项。

 编译  未提供源文本,请提供需要翻译的学术文本  运行时  测试
 编译  编译(*) -  运行时 -
 未提供源文本,请提供需要翻译的学术文本  未提供源文本,请提供需要翻译的学术文本 -  未提供源文本,请提供需要翻译的学术文本 -
 运行时  运行时 -  运行时 -
 测试  测试 -  测试 -


(*) 注意:本意是应该在运行时范围内,因此所有编译依赖都必须明确列出。然而,如果你所依赖的库扩展了另一个库中的类,那么这两个库都必须在编译时可用。因此,即使它们是传递性的,编译时依赖仍然保留在编译范围内。

 依赖管理


依赖管理部分是一种集中管理依赖信息的机制。当您有一组继承自公共父项目的项目时,可以将所有关于依赖的信息放入公共的 POM 中,并在子 POM 中对工件进行更简单的引用。该机制最好通过一些示例来说明。给定这两个扩展相同父项目的 POM:

 项目 A:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>group-a</groupId>
  6. <artifactId>artifact-a</artifactId>
  7. <version>1.0</version>
  8. <exclusions>
  9. <exclusion>
  10. <groupId>group-c</groupId>
  11. <artifactId>excluded-artifact</artifactId>
  12. </exclusion>
  13. </exclusions>
  14. </dependency>
  15. <dependency>
  16. <groupId>group-a</groupId>
  17. <artifactId>artifact-b</artifactId>
  18. <version>1.0</version>
  19. <type>bar</type>
  20. <scope>runtime</scope>
  21. </dependency>
  22. </dependencies>
  23. </project>

 项目 B:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>group-c</groupId>
  6. <artifactId>artifact-b</artifactId>
  7. <version>1.0</version>
  8. <type>war</type>
  9. <scope>runtime</scope>
  10. </dependency>
  11. <dependency>
  12. <groupId>group-a</groupId>
  13. <artifactId>artifact-b</artifactId>
  14. <version>1.0</version>
  15. <type>bar</type>
  16. <scope>runtime</scope>
  17. </dependency>
  18. </dependencies>
  19. </project>


这两个示例 POM 共享一个公共依赖,并且每个都有一个非平凡依赖。这些信息可以像这样放入父 POM 中:

  1. <project>
  2. ...
  3. <dependencyManagement>
  4. <dependencies>
  5. <dependency>
  6. <groupId>group-a</groupId>
  7. <artifactId>artifact-a</artifactId>
  8. <version>1.0</version>
  9.  
  10. <exclusions>
  11. <exclusion>
  12. <groupId>group-c</groupId>
  13. <artifactId>excluded-artifact</artifactId>
  14. </exclusion>
  15. </exclusions>
  16.  
  17. </dependency>
  18.  
  19. <dependency>
  20. <groupId>group-c</groupId>
  21. <artifactId>artifact-b</artifactId>
  22. <version>1.0</version>
  23. <type>war</type>
  24. <scope>runtime</scope>
  25. </dependency>
  26.  
  27. <dependency>
  28. <groupId>group-a</groupId>
  29. <artifactId>artifact-b</artifactId>
  30. <version>1.0</version>
  31. <type>bar</type>
  32. <scope>runtime</scope>
  33. </dependency>
  34. </dependencies>
  35. </dependencyManagement>
  36. </project>


然后,这两个子 POM 变得更加简单:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>group-a</groupId>
  6. <artifactId>artifact-a</artifactId>
  7. </dependency>
  8.  
  9. <dependency>
  10. <groupId>group-a</groupId>
  11. <artifactId>artifact-b</artifactId>
  12. <!-- This is not a jar dependency, so we must specify type. -->
  13. <type>bar</type>
  14. </dependency>
  15. </dependencies>
  16. </project>
  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>group-c</groupId>
  6. <artifactId>artifact-b</artifactId>
  7. <!-- This is not a jar dependency, so we must specify type. -->
  8. <type>war</type>
  9. </dependency>
  10.  
  11. <dependency>
  12. <groupId>group-a</groupId>
  13. <artifactId>artifact-b</artifactId>
  14. <!-- This is not a jar dependency, so we must specify type. -->
  15. <type>bar</type>
  16. </dependency>
  17. </dependencies>
  18. </project>


注意:在这两个依赖引用中,我们不得不指定元素。这是因为匹配依赖引用与依赖管理部分所需的最小信息集实际上是{groupId, artifactId, type, classifier}。在许多情况下,这些依赖将引用没有 classifier 的 jar 工件。这使我们能够将标识集简写为{groupId, artifactId},因为 type 字段的默认值是 jar ,而默认的 classifier 是 null。


第二,依赖管理部分的一个重要用途是控制传递依赖中使用的工件版本。例如,考虑以下项目:

 项目 A:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>maven</groupId>
  4. <artifactId>A</artifactId>
  5. <packaging>pom</packaging>
  6. <name>A</name>
  7. <version>1.0</version>
  8. <dependencyManagement>
  9. <dependencies>
  10. <dependency>
  11. <groupId>test</groupId>
  12. <artifactId>a</artifactId>
  13. <version>1.2</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>test</groupId>
  17. <artifactId>b</artifactId>
  18. <version>1.0</version>
  19. <scope>compile</scope>
  20. </dependency>
  21. <dependency>
  22. <groupId>test</groupId>
  23. <artifactId>c</artifactId>
  24. <version>1.0</version>
  25. <scope>compile</scope>
  26. </dependency>
  27. <dependency>
  28. <groupId>test</groupId>
  29. <artifactId>d</artifactId>
  30. <version>1.2</version>
  31. </dependency>
  32. </dependencies>
  33. </dependencyManagement>
  34. </project>

 项目 B:

  1. <project>
  2. <parent>
  3. <artifactId>A</artifactId>
  4. <groupId>maven</groupId>
  5. <version>1.0</version>
  6. </parent>
  7. <modelVersion>4.0.0</modelVersion>
  8. <groupId>maven</groupId>
  9. <artifactId>B</artifactId>
  10. <packaging>pom</packaging>
  11. <name>B</name>
  12. <version>1.0</version>
  13.  
  14. <dependencyManagement>
  15. <dependencies>
  16. <dependency>
  17. <groupId>test</groupId>
  18. <artifactId>d</artifactId>
  19. <version>1.0</version>
  20. </dependency>
  21. </dependencies>
  22. </dependencyManagement>
  23.  
  24. <dependencies>
  25. <dependency>
  26. <groupId>test</groupId>
  27. <artifactId>a</artifactId>
  28. <version>1.0</version>
  29. <scope>runtime</scope>
  30. </dependency>
  31. <dependency>
  32. <groupId>test</groupId>
  33. <artifactId>c</artifactId>
  34. <scope>runtime</scope>
  35. </dependency>
  36. </dependencies>
  37. </project>


当在项目 B 上运行 maven 时,无论在它们的 POM 中指定了哪个版本,都将使用 a、b、c 和 d 的 1.0 版本。


  • a 和 c 均被声明为项目的依赖项,因此由于依赖项调解,使用版本 1.0。两者也具有运行时作用域,因为它被直接指定。

  • b 在 B 的父依赖管理部分定义,由于依赖管理优先于传递依赖的依赖调解,如果它在 a 或 c 的 POM 中被引用,则将选择版本 1.0。b 还具有编译作用域。

  • 最后,由于 d 在 B 的依赖管理部分被指定,如果 d 是 a 或 c 的依赖(或传递依赖),则将选择版本 1.0——这再次是因为依赖管理优先于依赖调解,也因为当前 POM 的声明优先于其父 POM 的声明。


注意:依赖管理不会影响同一有效 POM 中使用的任何插件的(传递性)依赖,只会影响(传递性)项目依赖。


关于依赖管理标签的参考信息可在项目描述符参考中找到。

 导入依赖项


上一节的例子描述了如何通过继承来指定管理依赖。然而,在较大的项目中,由于一个项目只能继承自单个父类,可能无法实现这一点。为了适应这种情况,项目可以从其他项目导入管理依赖。这是通过声明一个 POM 工件作为具有“导入”范围的依赖来实现的。

 项目 B:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>maven</groupId>
  4. <artifactId>B</artifactId>
  5. <packaging>pom</packaging>
  6. <name>B</name>
  7. <version>1.0</version>
  8.  
  9. <dependencyManagement>
  10. <dependencies>
  11. <dependency>
  12. <groupId>maven</groupId>
  13. <artifactId>A</artifactId>
  14. <version>1.0</version>
  15. <type>pom</type>
  16. <scope>import</scope>
  17. </dependency>
  18. <dependency>
  19. <groupId>test</groupId>
  20. <artifactId>d</artifactId>
  21. <version>1.0</version>
  22. </dependency>
  23. </dependencies>
  24. </dependencyManagement>
  25.  
  26. <dependencies>
  27. <dependency>
  28. <groupId>test</groupId>
  29. <artifactId>a</artifactId>
  30. <version>1.0</version>
  31. <scope>runtime</scope>
  32. </dependency>
  33. <dependency>
  34. <groupId>test</groupId>
  35. <artifactId>c</artifactId>
  36. <scope>runtime</scope>
  37. </dependency>
  38. </dependencies>
  39. </project>


假设 A 是前一个例子中定义的 POM,最终结果将相同。A 的所有管理依赖项都将纳入 B 中,除了 d,因为它在此 POM 中定义。

 项目 X:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>maven</groupId>
  4. <artifactId>X</artifactId>
  5. <packaging>pom</packaging>
  6. <name>X</name>
  7. <version>1.0</version>
  8.  
  9. <dependencyManagement>
  10. <dependencies>
  11. <dependency>
  12. <groupId>test</groupId>
  13. <artifactId>a</artifactId>
  14. <version>1.1</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>test</groupId>
  18. <artifactId>b</artifactId>
  19. <version>1.0</version>
  20. <scope>compile</scope>
  21. </dependency>
  22. </dependencies>
  23. </dependencyManagement>
  24. </project>

 项目 Y:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>maven</groupId>
  4. <artifactId>Y</artifactId>
  5. <packaging>pom</packaging>
  6. <name>Y</name>
  7. <version>1.0</version>
  8.  
  9. <dependencyManagement>
  10. <dependencies>
  11. <dependency>
  12. <groupId>test</groupId>
  13. <artifactId>a</artifactId>
  14. <version>1.2</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>test</groupId>
  18. <artifactId>c</artifactId>
  19. <version>1.0</version>
  20. <scope>compile</scope>
  21. </dependency>
  22. </dependencies>
  23. </dependencyManagement>
  24. </project>

 项目 Z:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>maven</groupId>
  4. <artifactId>Z</artifactId>
  5. <packaging>pom</packaging>
  6. <name>Z</name>
  7. <version>1.0</version>
  8. <dependencyManagement>
  9. <dependencies>
  10. <dependency>
  11. <groupId>maven</groupId>
  12. <artifactId>X</artifactId>
  13. <version>1.0</version>
  14. <type>pom</type>
  15. <scope>import</scope>
  16. </dependency>
  17. <dependency>
  18. <groupId>maven</groupId>
  19. <artifactId>Y</artifactId>
  20. <version>1.0</version>
  21. <type>pom</type>
  22. <scope>import</scope>
  23. </dependency>
  24. </dependencies>
  25. </dependencyManagement>
  26. </project>


在上面的例子中,Z 从 X 和 Y 中导入管理依赖。然而,X 和 Y 都包含依赖项 a。在这里,由于 X 被声明在先,且 a 未在 Z 的依赖管理中声明,将使用 a 的 1.1 版本。


此过程是递归的。例如,如果 X 导入另一个 POM,Q,当 Z 被处理时,将简单地显示 Q 的所有管理依赖项都定义在 X 中。


物料清单(BOM)POMs


导入在用于定义一个“库”中相关工件时最为有效,这些工件通常属于一个多项目构建的一部分。一个项目使用这些库中的一个或多个工件的情况相当普遍。然而,有时很难保持使用这些工件的项目版本与库中分发的版本同步。下面的模式说明了如何为其他项目创建一个“物料清单”(BOM)。


项目的基础是 BOM POM。它定义了将在库中创建的所有构件的版本。希望使用该库的其他项目应在它们的 POM 的依赖管理部分导入此 POM。

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.test</groupId>
  5. <artifactId>bom</artifactId>
  6. <version>1.0.0</version>
  7. <packaging>pom</packaging>
  8. <properties>
  9. <project1Version>1.0.0</project1Version>
  10. <project2Version>1.0.0</project2Version>
  11. </properties>
  12. <dependencyManagement>
  13. <dependencies>
  14. <dependency>
  15. <groupId>com.test</groupId>
  16. <artifactId>project1</artifactId>
  17. <version>${project1Version}</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>com.test</groupId>
  21. <artifactId>project2</artifactId>
  22. <version>${project2Version}</version>
  23. </dependency>
  24. </dependencies>
  25. </dependencyManagement>
  26. <modules>
  27. <module>parent</module>
  28. </modules>
  29. </project>


父级子项目以 BOM POM 为其父级。它是一个正常的多个项目 pom。

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <parent>
  5. <groupId>com.test</groupId>
  6. <version>1.0.0</version>
  7. <artifactId>bom</artifactId>
  8. </parent>
  9.  
  10. <groupId>com.test</groupId>
  11. <artifactId>parent</artifactId>
  12. <version>1.0.0</version>
  13. <packaging>pom</packaging>
  14.  
  15. <dependencyManagement>
  16. <dependencies>
  17. <dependency>
  18. <groupId>log4j</groupId>
  19. <artifactId>log4j</artifactId>
  20. <version>1.2.12</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>commons-logging</groupId>
  24. <artifactId>commons-logging</artifactId>
  25. <version>1.1.1</version>
  26. </dependency>
  27. </dependencies>
  28. </dependencyManagement>
  29. <modules>
  30. <module>project1</module>
  31. <module>project2</module>
  32. </modules>
  33. </project>


接下来是实际项目的 POMs。

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <parent>
  5. <groupId>com.test</groupId>
  6. <version>1.0.0</version>
  7. <artifactId>parent</artifactId>
  8. </parent>
  9. <groupId>com.test</groupId>
  10. <artifactId>project1</artifactId>
  11. <version>${project1Version}</version>
  12. <packaging>jar</packaging>
  13.  
  14. <dependencies>
  15. <dependency>
  16. <groupId>log4j</groupId>
  17. <artifactId>log4j</artifactId>
  18. </dependency>
  19. </dependencies>
  20. </project>
  21.  
  22. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  23. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  24. <modelVersion>4.0.0</modelVersion>
  25. <parent>
  26. <groupId>com.test</groupId>
  27. <version>1.0.0</version>
  28. <artifactId>parent</artifactId>
  29. </parent>
  30. <groupId>com.test</groupId>
  31. <artifactId>project2</artifactId>
  32. <version>${project2Version}</version>
  33. <packaging>jar</packaging>
  34.  
  35. <dependencies>
  36. <dependency>
  37. <groupId>commons-logging</groupId>
  38. <artifactId>commons-logging</artifactId>
  39. </dependency>
  40. </dependencies>
  41. </project>


接下来的项目展示了如何在不指定依赖项目的版本的情况下,使用该库在另一个项目中。

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.test</groupId>
  5. <artifactId>use</artifactId>
  6. <version>1.0.0</version>
  7. <packaging>jar</packaging>
  8.  
  9. <dependencyManagement>
  10. <dependencies>
  11. <dependency>
  12. <groupId>com.test</groupId>
  13. <artifactId>bom</artifactId>
  14. <version>1.0.0</version>
  15. <type>pom</type>
  16. <scope>import</scope>
  17. </dependency>
  18. </dependencies>
  19. </dependencyManagement>
  20. <dependencies>
  21. <dependency>
  22. <groupId>com.test</groupId>
  23. <artifactId>project1</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>com.test</groupId>
  27. <artifactId>project2</artifactId>
  28. </dependency>
  29. </dependencies>
  30. </project>


最后,在创建需要导入依赖的项目时,请注意以下几点:


  • 不要尝试导入当前 POM 中定义的子模块中的 POM。尝试这样做会导致构建失败,因为它将无法找到该 POM。

  • 从不声明 POM 导入的 POM 是目标 POM 的父级(或祖父级等)。无法解决循环依赖,将会抛出异常。

  • 当引用具有传递依赖的 POM 的工件时,项目需要指定这些工件的版本作为管理依赖项。如果不这样做,由于工件可能未指定版本,将导致构建失败。(在任何情况下,这都应被视为最佳实践,因为它可以防止工件版本在构建之间发生变化)。


从 Maven 4.0 开始,引入了一种新的特定 BOM 打包方式。它允许定义在项目中不作为父项目使用的 BOM,同时仍然与 Maven 3.X 客户端和项目保持完全兼容。这种 BOM 打包在安装/部署时转换为更常见的 POM 打包,利用 Maven 4 的构建/消费者 POM 功能。因此,它提供了与 Maven 3.x 的完全兼容性。

  1. <project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 http://maven.apache.org/xsd/maven-4.1.0.xsd">
  3. <parent>
  4. <groupId>com.test</groupId>
  5. <version>1.0.0</version>
  6. <artifactId>parent</artifactId>
  7. </parent>
  8. <groupId>com.test</groupId>
  9. <artifactId>bom</artifactId>
  10. <version>1.0.0</version>
  11. <packaging>bom</packaging>
  12. <properties>
  13. <project1Version>1.0.0</project1Version>
  14. <project2Version>1.0.0</project2Version>
  15. </properties>
  16. <dependencyManagement>
  17. <dependencies>
  18. <dependency>
  19. <groupId>com.test</groupId>
  20. <artifactId>project1</artifactId>
  21. <version>${project1Version}</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>com.test</groupId>
  25. <artifactId>project2</artifactId>
  26. <version>${project2Version}</version>
  27. </dependency>
  28. </dependencies>
  29. </dependencyManagement>
  30. </project>

 系统依赖

Important note: This is deprecated.


依赖项具有作用域系统始终可用,且不在仓库中查找。它们通常用于告知 Maven 关于由 JDK 或 VM 提供的依赖项。因此,系统依赖项对于解决现在由 JDK 提供但之前作为单独下载提供的工件依赖项特别有用。典型示例包括 JDBC 标准扩展或 Java 身份验证和授权服务(JAAS)。


一个简单的例子将是:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>javax.sql</groupId>
  6. <artifactId>jdbc-stdext</artifactId>
  7. <version>2.0</version>
  8. <scope>system</scope>
  9. <systemPath>${java.home}/lib/rt.jar</systemPath>
  10. </dependency>
  11. </dependencies>
  12. ...
  13. </project>


如果您的工件由 JDK 的 tools.jar 提供,系统路径将如下定义:

  1. <project>
  2. ...
  3. <dependencies>
  4. <dependency>
  5. <groupId>sun.jdk</groupId>
  6. <artifactId>tools</artifactId>
  7. <version>1.5.0</version>
  8. <scope>system</scope>
  9. <systemPath>${java.home}/../lib/tools.jar</systemPath>
  10. </dependency>
  11. </dependencies>
  12. ...
  13. </project>