Maven 依赖解析和范围覆盖

发布于 2024-12-07 05:17:55 字数 2801 浏览 0 评论 0原文

免责声明

(我最初以非常详细的方式提出问题 在这里。我在这里摘录了它,因为 maven-users 邮件列表在这个问题上已经保持沉默。) (不仅仅是另一个新手问题)

参考

我的参考资料是 http://maven.apache.org/guides/introduction /introduction-to-dependency-mechanism.html#Dependency_Management;如果这已经过时或错误,请在本次讨论中告诉我。

问题

该文档中有一个部分以“第二个,非常重要......”开头。接下来,我将参考该部分的项目 AB,并从中摘录。

在该部分中,您将看到项目 A 有一个 部分,除其他外,该部分定义了一个工件 c,因为具有范围 compile

<!-- In A's pom.xml; condensed for brevity -->
<dependencyManagement>
    <dependency>
        <groupId>test</groupId>
        <artifactId>c</artifactId>
        <version>1.0</version>
        <scope>compile</scope> <!-- look: compile scope -->
    </dependency>
</dependencyManagement>

然后您将看到项目 Bpom.xml,它 (a) 继承自项目 A (从而继承了它的dependencyManagement 部分)和 (b) 建立对工件 c 的依赖关系,而无需指定其版本。您还会注意到,对工件 c 的依赖将 c 的范围覆盖为 runtime,而不是 compile

<!-- In B's pom.xml, whose parent is A's pom.xml (above); condensed for brevity -->
<dependencies>
    <dependency>
        <groupId>test</groupId>
        <artifactId>c</artifactId>
        <scope>runtime</scope> <!-- look: runtime scope -->
    </dependency>
</dependencies>

您将再次注意到,没有 元素,但有一个 runtime 元素。

我对此的解释是,归根结底,B 将取决于 中工件 c1.0 版本运行时范围,而不是编译范围。

这是正确的吗? 我的 maven-ear-plugin 错误基于以下事实:这是预期的行为。当 maven-ear-plugin 构建 .ear 文件时,不会发生这种情况。

接下来,如果这是正确的,我还希望如果工件 c 具有任何可传递的 runtime 依赖项,它们将在 B中可用>runtime 类路径(由 http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope)。

这是正确的吗?

Disclaimer

(I originally asked the question in a very detailed manner over here. I've excerpted it here as the maven-users mailing list has gone quiet on this question.) (not just another newbie question)

Reference

My reference material is
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management; please let me know in this discussion if this is outdated or wrong.

Question

There is a section in that document that begins with "A second, and very important...". In what follows I'll refer to that section's projects A and B, and will excerpt from them.

In that section, you will see that project A has a <dependencyManagement> section that--among other things--defines an artifact, c, as having scope compile:

<!-- In A's pom.xml; condensed for brevity -->
<dependencyManagement>
    <dependency>
        <groupId>test</groupId>
        <artifactId>c</artifactId>
        <version>1.0</version>
        <scope>compile</scope> <!-- look: compile scope -->
    </dependency>
</dependencyManagement>

Then you will see a pom.xml for project B that (a) inherits from project A (thus inheriting its dependencyManagement section) and (b) establishes a dependency on artifact c, without having to specify its version. You will also notice that the dependency on artifact c overrides the scope of c to be runtime, not compile:

<!-- In B's pom.xml, whose parent is A's pom.xml (above); condensed for brevity -->
<dependencies>
    <dependency>
        <groupId>test</groupId>
        <artifactId>c</artifactId>
        <scope>runtime</scope> <!-- look: runtime scope -->
    </dependency>
</dependencies>

Again, you'll note that there is no <version> element, but there is a <scope>runtime</scope> element.

My interpretation of this is that when all is said and done, B will depend on version 1.0 of artifact c in runtime scope, not compile scope.

Is that correct? My maven-ear-plugin bug rests on the fact that this is the expected behavior. It is not what happens when the maven-ear-plugin builds an .ear file.

Next, if that's correct, I would also expect that if artifact c had any transitive runtime dependencies they would be available in B's runtime classpath (as defined by the somewhat baffling table in http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope).

Is that correct?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

很糊涂小朋友 2024-12-14 05:17:55

bug 中发布的示例项目上运行 mvn dependency:tree上面指定的link

[INFO] Building MEAR-143 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143 ---
[INFO] ljnelson:mear-143:pom:1.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.8.2:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MEAR-143 Leaf 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143-leaf ---
[INFO] ljnelson:mear-143-leaf:jar:1.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.8.2:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MEAR-143 Middle 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143-middle ---
[INFO] ljnelson:mear-143-middle:jar:1.0-SNAPSHOT
[INFO] +- ljnelson:mear-143-leaf:jar:1.0-SNAPSHOT:runtime
[INFO] \- junit:junit:jar:4.8.2:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MEAR-143 EAR 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143-ear ---
[INFO] ljnelson:mear-143-ear:ear:1.0-SNAPSHOT
[INFO] +- ljnelson:mear-143-middle:jar:1.0-SNAPSHOT:runtime
[INFO] |  \- ljnelson:mear-143-leaf:jar:1.0-SNAPSHOT:test (scope managed from ru
ntime)
[INFO] \- junit:junit:jar:4.8.2:test

mear-143-middlemear-143-leaf的依赖scope,其中依赖是明确的定义确实是runtime,覆盖父 pom mear-143dependencyManagement 部分中定义的 test 范围。

mear-143-ear 中,mear-143-leaf传递包含在内。这里,mear-143dependencyManagement 中定义的 test 范围优先于继承的 runtime 范围。

我想这与您上面提到的部分的第二个要点中指定的内容一致。在此引用并以粗体和斜体突出显示相关部分:

b 是在 B 的父级依赖管理部分中定义的,因为
依赖管理优先于依赖调解
传递依赖,如果是的话,将选择 1.0 版本
在 a 或 c 的 pom 中引用。 b 也将具有编译范围


Running mvn dependency:tree on the sample project posted in the bug link specified above,

[INFO] Building MEAR-143 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143 ---
[INFO] ljnelson:mear-143:pom:1.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.8.2:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MEAR-143 Leaf 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143-leaf ---
[INFO] ljnelson:mear-143-leaf:jar:1.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.8.2:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MEAR-143 Middle 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143-middle ---
[INFO] ljnelson:mear-143-middle:jar:1.0-SNAPSHOT
[INFO] +- ljnelson:mear-143-leaf:jar:1.0-SNAPSHOT:runtime
[INFO] \- junit:junit:jar:4.8.2:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MEAR-143 EAR 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ mear-143-ear ---
[INFO] ljnelson:mear-143-ear:ear:1.0-SNAPSHOT
[INFO] +- ljnelson:mear-143-middle:jar:1.0-SNAPSHOT:runtime
[INFO] |  \- ljnelson:mear-143-leaf:jar:1.0-SNAPSHOT:test (scope managed from ru
ntime)
[INFO] \- junit:junit:jar:4.8.2:test

The dependency scope of mear-143-leaf in mear-143-middle, where the dependency is explicitly defined is indeed runtime, overriding the test scope defined in the dependencyManagement section of parent pom, mear-143.

In mear-143-ear, mear-143-leaf gets included transitively. Here the test scope defined in dependencyManagement of mear-143 takes precedence over the inherited runtime scope.

This, I guess is in line with what is specified in the second bullet point in the section you have referred above. Quoting it here and highlighting in bold and italics the relevant parts:

b is defined in B's parent's dependency management section and since
dependency management takes precedence over dependency mediation for
transitive dependencies
, version 1.0 will be selected should it be
referenced in a or c's pom. b will also have compile scope

独自唱情﹋歌 2024-12-14 05:17:55

所选答案足以阐明关键点:dependencyManagement 是否优先取决于子依赖项是显式声明还是传递声明。

作为一个优点,我刚刚创建了一个有关版本和版本的摘要。范围解析完全解决这个问题:

dependency

假设依赖项 A 在不同的方式,每个都有不同的版本......哪个版本会最后获胜?

只需记住图中的三个规则即可:

  • 显式声明>依赖管理声明声明>隐式传递声明
  • 第一个声明>第2声明
  • 子声明>父声明

,您将找出图中红色编号列表所示的优先级顺序。

The selected answer is good enough to clarify the key point that whether dependencyManagement takes precedence relies on whether the child dependency is declared explicitly or transitively.

As a plus, I just created a summary concerned with version & scope resolution to kill this problem totally:

dependency

Assuming that a dependency A is declared eight times in different ways, and each with a different version... which version will win last?

just remember the three rules in the picture:

  • explicit declaration > dependency-management declaration > implicit transitive declaration
  • 1st declaration > 2nd declaration
  • child declaration > parent declaration

and you will figure out the priority sequence shown as red numbered list in the picture.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文