Maven 依赖管理版本在传递依赖中被忽略
Posted
技术标签:
【中文标题】Maven 依赖管理版本在传递依赖中被忽略【英文标题】:Maven dependencyManagement version ignored in transitive dependencies 【发布时间】:2015-04-03 11:29:40 【问题描述】:尽管我有一个指定版本 18 的
快速总结:
gwizard-example
取决于 gwizard-config
gwizard-config
有一个父 pom,gwizard-parent
gwizard-parent
有 谢天谢地,这是一个开源项目,因此您可以直接查看 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 依赖管理 -- 依赖配置 & 依赖传递 (概念 & 依赖传递冲突问题 & 可选依赖(不透明) & 排除依赖(不需要))
Gradle-5.3:依赖-管理依赖的版本(传递(transitive)排除(exclude)强制(force)动态版本(+))