依赖管理和范围

问题描述 投票:0回答:5

我通常会在

<dependencyManagement>
中放置
parent-project/pom.xml
部分。这个
<dependencyManagement>
部分包含我的子模块的所有依赖项的声明和版本,如下所示(即没有
<scope>
元素):

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
    </dependency>
  </dependencies> 
</dependencyManagement>

在所有子模块(即 moduleX/pom.xml)中,我有:

  <dependencies>
    <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <scope>test</scope>
    </dependency>
  </dependencies> 

显然,在这个示例中,我针对相同的依赖项多次重复

<scope>test</scope>
(在每个需要 junit 的子模块中重复一次)。

我的问题是:
关于

<scope>
声明的最佳做法是什么?
是不是放在
<dependencyManagement>
比较好?
或者最好将其放在子模块的
<dependencies>
部分(就像在这篇文章中一样)?为什么?
这个问题有明确的答案吗?

maven dependency-management
5个回答
76
投票

聚会有点晚了,但我会加我的两分钱。

我最近遇到了一个非常难以调试的问题。
我有一个父 pom,用于管理多个项目之间的依赖关系。我设置了它们之间常见的所有依赖项,包括

groupId
artifactId
version
最常见的
scope

我的想法是,如果它符合最常见的
scope
,我就不必在每个项目的实际依赖项部分中包含范围。
当其中一些依赖项显示为传递依赖项时,就会出现问题。例如,如果:

  • A 在编译范围内依赖于 B。
  • B 在编译范围内依赖于 C。
  • C 设置为在父级的
    dependencyManagement
    中提供。

则确定A对C的传递依赖是有的。我不太确定这是否有意义,但这确实令人困惑。

无论如何,省去麻烦,把

scope
排除在你的
dependencyManagement
之外。


38
投票

dependencyManagement
只是在这里定义所有项目子模块的依赖项版本,本节中唯一相关的范围是 BOM 的
import

范围必须在

dependencies
部分定义。

(对于给定的依赖项,它确定使用上下文。它允许仅在需要执行时包含依赖项。例如,ear 不会与 Java-ee 依赖项(范围

provided
)一起打包,因为它会发现它们位于目标服务器上。)

[编辑]

第一个语句有一个例外,

provided
部分中的范围
dependencyManagement
将覆盖
dependencies
部分中定义的范围。请参阅 DependencyManagement 强制范围


9
投票

与其他答案一样,最佳实践是从 dependencyManagement 中排除范围,并在定义依赖项时显式指定它。在极少数情况下,您希望在不同范围内使用相同依赖项的不同版本,例如,编译应用程序时使用一个版本,而在运行应用程序时使用不同版本 - 我能想到的唯一情况是您想要显式运行您的应用程序针对不同版本的库进行测试,以防用户使用该版本而不是您指定的版本。

如果您在 dependencyManagement 中定义范围,它会将该版本的使用限制为仅定义的范围 - 因此任何其他范围都将选取依赖项的随机版本。昨天我遇到了这个问题,当时我们在 dependencyManagement 中定义了带有测试范围的 junit 4.12,但是我们的通用测试框架模块使用带有编译范围的 junit,所以它选择了版本 4.8.2。


2
投票

虽然来晚了,但最新的 Maven 对于传递依赖范围和依赖管理细节有非常清晰的文档,包括一个示例。 https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#dependency-scope 从文档中我们可以看到:

  1. 当传递范围不同时,有优先规则来决定应用哪一个。乍一看规则表很复杂,但对于大多数情况来说这是常识。
  2. 文档特别提供了依赖范围和依赖管理组合案例的示例。最终它遵循 1 中指定的规则。

作为结论,建议以最“常见”的方式包含范围。如果存在传递、冲突或走投无路的情况,我们需要仔细检查优先规则。


1
投票

对于任何范围,将单个依赖项添加到依赖项管理中都没有任何好处。你所拥有的只是重复。如果您希望版本可配置,请添加一个属性并在您的依赖项中使用它:

<properties>
        <junit.version>4.10</junit.version> 
    ...
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
    </dependency>
</dependencies>

但是,在某些情况下,依赖关系管理会发挥作用 - 当您使用

boms
来编排更大的工件集合的版本时,例如使用某个版本的 Java EE 实现:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.jboss.bom</groupId>
            <artifactId>jboss-javaee-6.0-with-tools</artifactId>
            <version>${javaee6.with.tools.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
....
© www.soinside.com 2019 - 2024. All rights reserved.