【问题标题】:Maven dependencyManagement version ignored in transitive dependenciesMaven 依赖管理版本在传递依赖中被忽略
【发布时间】: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-parentgwizard-configgwizard-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

【问题讨论】:

    标签: maven maven-3


    【解决方案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,但它对我不起作用。我仍然看到不正确的库版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 2015-10-13
    • 2019-04-07
    • 2021-07-11
    相关资源
    最近更新 更多