Maven 依赖管理版本在传递依赖中被忽略

Posted

技术标签:

【中文标题】Maven 依赖管理版本在传递依赖中被忽略【英文标题】:Maven dependencyManagement version ignored in transitive dependencies 【发布时间】:2015-04-03 11:29:40 【问题描述】:

尽管我有一个指定版本 18 的 部分,但 Maven 正在传递地引入 guava 版本 16。

快速总结:

gwizard-example 取决于 gwizard-config gwizard-config 有一个父 pom,gwizard-parent gwizard-parent 指定 guava 版本 18

谢天谢地,这是一个开源项目,因此您可以直接查看 poms:gwizard-parent、gwizard-config、gwizard-example。但是,这是gwizard-parent 中的重要部分:

<properties>
    <guava.version>18.0</guava.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>$guava.version</version>
        </dependency>
    </dependencies>
</dependencyManagement>

...以及在 gwizard-example 中声明的简洁依赖:

<properties>
    <gwizard.version>0.5</gwizard.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.gwizard</groupId>
        <artifactId>gwizard-config</artifactId>
        <version>$gwizard.version</version>
    </dependency>
</dependencies>

gwizard-config 的依赖树正确显示 guava 18:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ gwizard-config ---
[INFO] org.gwizard:gwizard-config:jar:0.5
[INFO] +- com.google.inject:guice:jar:4.0-beta5:compile
[INFO] |  \- com.google.guava:guava:jar:18.0:compile

但是,gwizard-example 的依赖关系树显示 guava 16(这会导致问题):

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ gwizard-example ---
[INFO] org.gwizard:gwizard-example:jar:1.0-SNAPSHOT
[INFO] +- org.gwizard:gwizard-config:jar:0.5:compile
[INFO] |  +- com.google.inject:guice:jar:4.0-beta5:compile
[INFO] |  |  \- com.google.guava:guava:jar:16.0.1:compile

这是使用 Maven v3.2.5。我很困惑。帮忙?

可能相关:dependencyManagement in parent ignored

UPDATE:github上链接的pom正在变化;在gwizard-example 中添加对gwizard-services 的依赖项(直接声明一个番石榴dep)“修复”了这个问题。这里仍然存在某种不良的潜在行为。

更新:创建this JIRA issue

【问题讨论】:

【参考方案1】:

有一件简单的事情。 dependencyManagement 没有声明真正使用的依赖项,它只是定义可以使用的版本等。

如果你定义这样的东西,它不会导致改变。

<properties>
    <guava.version>18.0</guava.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>$guava.version</version>
        </dependency>
    </dependencies>
</dependencyManagement>

如果你真的想覆盖树中使用的版本,你需要定义一个真正的依赖: 因此,基于上述定义,您还需要添加以下内容:

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
    </dependency>
</dependencies>

如果您已添加此内容,请稍后通过 mvn dependency:tree 检查。

【讨论】:

这没有意义;或者至少,它似乎不是很有用。 dependencyManagement 的重点是允许我为传递依赖项指定一个版本。在这里,番石榴是通过 guice 传递的。为什么我的dependencyManagement 不控制guice 拉入的版本?如果我的库不直接依赖于 guava,为什么还要将 guava 指定为依赖项? 对此的简单回答是,因为 guice 的 pom 的维护者决定使用其他版本。所以你不能直接控制那里使用的 pom。你只能间接控制它。顺便说一句:dependencyManagement 无法控制。 dependencies 会改为,因为它更接近您的项目。 @khmarbaise 这是否意味着如果 example 使用 guava 18 定义了一个 dependencyManagement 部分,它仍然会从 gwizard-config 中提取 guava:16,还是我理解错误?这是令人震惊的部分,而不是传递的父依赖管理被忽略的事实。因为,那么,dependencyManagement 对于管理传递依赖版本将完全没有用 不,我只是用这些特定的依赖项对其进行了测试,它确实按预期工作,而不是按规定工作。如果您放置您建议的第一个代码部分,那么 guava 18 将从配置依赖传递到示例中。您不需要像第二部分中所述声明传递依赖项(番石榴),以使依赖管理部分生效(即使该番石榴版本在传递依赖项上未引用,也需要 18 个) @Whimusical 你是对的。事实上,我认为我们只需要解决与here 问题相反的问题。我们覆盖了一个版本,这会导致轻微的误解。 imo 答案和问题都不再是最新的了。【参考方案2】:

在这种情况下,Maven 无法解决版本传递依赖问题。

这个问题可以通过使用 maven bom 概念来解决。

在以下链接中查看 bom 的 maven 文档 http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management

这是另一个解释 bom 用法的博客 http://howtodoinjava.com/maven/maven-bom-bill-of-materials-dependency/

在您的情况下,要解决此问题,您需要在项目 gwizard-example 的 dependencyManagement 部分中添加以下依赖项。

     <dependency>
         <groupId>org.gwizard</groupId>
         <artifactId>gwizard-parent</artifactId>
         <version>$gwizard.version</version>
         <type>pom</type>
         <scope>import</scope>
     </dependency>

【讨论】:

这没有意义;或者至少,它似乎不是很有用。 dependencyManagement 的重点是 allow_me_to_specify_a_version 用于传递依赖,而不是继承另一个项目的版本... 我按照您的建议尝试了 import parent,但它对我不起作用。我仍然看到不正确的库版本。

以上是关于Maven 依赖管理版本在传递依赖中被忽略的主要内容,如果未能解决你的问题,请参考以下文章

04_项目一众筹00_05Maven依赖概念,依赖范围依赖传递性依赖的原则:解决jar包冲突依赖排除统一版本管理

Maven--依赖管理

Maven 依赖管理 -- 依赖配置 & 依赖传递 (概念 & 依赖传递冲突问题 & 可选依赖(不透明) & 排除依赖(不需要))

Gradle-5.3:依赖-管理依赖的版本(传递(transitive)排除(exclude)强制(force)动态版本(+))

依赖管理的传递效应

maven依赖管理(依赖配置依赖传递依赖冲突依赖范围)