Maven:不正确(和片状)传递依赖版本

时间:2017-06-16 14:02:02

标签: java maven jar dependency-management

当我运行mvn dependency:tree -Dverbose时,我会看到以下内容:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ reddit_digest ---
...
[INFO] +- com.rajivprab:sava:jar:1.2.0:compile
[INFO] |  +- com.rajivprab:cava:jar:1.5.0:compile
[INFO] |  |  +- org.apache.commons:commons-lang3:jar:3.5:compile
...
[INFO] |  |  \- com.google.guava:guava:jar:20.0:compile

这是非常令人惊讶的,因为the cava artifact has guava version-22 specified

如果我继续将guava版本22添加为对我的项目的直接依赖,并再次运行mvn dependency:tree -Dverbose,我现在看到以下内容,其中cava的番石榴版本被神奇地修复为应该是什么(22)。

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ reddit_digest ---
...
[INFO] +- com.google.guava:guava:jar:22.0:compile
[INFO] +- com.rajivprab:sava:jar:1.2.0:compile
[INFO] |  +- com.rajivprab:cava:jar:1.5.0:compile
[INFO] |  |  +- org.apache.commons:commons-lang3:jar:3.5:compile
...
[INFO] |  |  \- (com.google.guava:guava:jar:22.0:compile - omitted for duplicate)

导致番石榴传递依赖版本以如此意外的方式运行的原因是什么?

在cava上运行依赖树:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ cava ---
....
[INFO] com.rajivprab:cava:jar:1.5.0
[INFO] +- com.google.guava:guava:jar:22.0:compile
....
[INFO] \- com.google.truth:truth:jar:0.33:test
[INFO]    +- (com.google.guava:guava:jar:20.0:test - omitted for conflict with 22.0)

在sava上运行依赖树,并查找guava的所有实例:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ sava ---
[INFO] com.rajivprab:sava:jar:1.2.0
[INFO] +- com.rajivprab:cava:jar:1.5.0:compile
...
[INFO] |  \- com.google.guava:guava:jar:22.0:compile
...
[INFO] +- com.google.truth:truth:jar:0.33:test
[INFO] |  +- (com.google.guava:guava:jar:20.0:test - omitted for conflict with 22.0)
...
[INFO] +- org.glassfish.jersey.media:jersey-media-multipart:jar:2.25.1:compile
[INFO] |  +- org.glassfish.jersey.core:jersey-common:jar:2.25.1:compile
[INFO] |  |  +- (javax.ws.rs:javax.ws.rs-api:jar:2.0.1:compile - omitted for duplicate)
[INFO] |  |  +- javax.annotation:javax.annotation-api:jar:1.2:compile
[INFO] |  |  +- org.glassfish.jersey.bundles.repackaged:jersey-guava:jar:2.25.1:compile

我的maven版本:

Apache Maven 3.5.0 (ff8f5e7444045639af65f6095c62210b5713f426; 2017-04-03T15:39:06-04:00)
Maven home: /usr/local/Cellar/maven/3.5.0/libexec
Java version: 1.8.0_92, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.12.5", arch: "x86_64", family: "mac"

1 个答案:

答案 0 :(得分:1)

v22深三层,v20深两层。 Maven的依赖中介选择“最接近的定义”,即v20。

  

依赖关系中介 - 确定在遇到多个版本的工件时将使用哪个版本的依赖关系。目前,Maven 2.0仅支持使用“最接近的定义”,这意味着它将在依赖树中使用与项目最接近的依赖项版本。您可以通过在项目的POM中明确声明它来保证版本。请注意,如果两个依赖关系版本在依赖关系树中处于相同的深度,则直到Maven 2.0.8没有定义哪一个会赢,但是自Maven 2.0.9开始,它就是声明中的顺序:第一个声明获胜。

     

“最近定义”表示所使用的版本将是依赖树中与项目最接近的版本,例如。如果A,B和C的依赖关系被定义为A - >; B - > C - > D 2.0和A - > E - > D 1.0,然后在构建A时将使用D 1.0,因为从A到D到E的路径更短。您可以在A中向D 2.0显式添加依赖项以强制使用D 2.0

来源:https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Transitive_Dependencies

这个SO答案可以为您提供有关依赖性调解策略背后原因的更详细说明:https://stackoverflow.com/a/43165652

您有两个简单的选择:

  1. 将番石榴v22添加到您的pom中,使其最近。
  2. 为谷歌真相依赖添加排除。这里有一个例子:https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management