当依赖树中存在两个或更多版本的依赖时,Maven如何选择传递依赖的版本? [英] How does Maven Choose the Version of a Transitive Dependency when Two or More Versions of that Dependency Exist in the Dependency Tree?
问题描述
我有一个项目,该项目依赖于我维护的称为microservices-common的库.进而,microservices-common库取决于 commons-codec:1.11
.但是,当我尝试在项目中使用常见的microservices时, commons-codec:1.10
最终出现在我的类路径上,并且我的代码无法编译,因为microservices-common试图使用 commons-codec:1.11
中的> org.apache.commons.codec.digest.DigestUtils 构造函数,但未出现在 commons-codec:1.10 中代码>.
I've got a project that depends on a library that I maintain called microservices-common. The microservices-common library in turn depends on commons-codec:1.11
. However, when I attempt to use microservices-common in my project, commons-codec:1.10
ends up on my classpath, and my code fails to compile, because microservices-common is attempting to use a org.apache.commons.codec.digest.DigestUtils
constructor that was added to commons-codec:1.11
, but isn't present in commons-codec:1.10
.
以下是微服务常见的依赖项树的相关部分:
Here's the relevant portion of the dependency tree for microservices-common:
[INFO] com.myproject:microservice-common:jar:1.0-SNAPSHOT
[INFO] +- commons-codec:commons-codec:jar:1.11:compile
[INFO] +- org.apache.httpcomponents:httpclient:jar:4.5.5:compile
[INFO] | \- (commons-codec:commons-codec:jar:1.10:compile - omitted for conflict with 1.11)
[INFO] \- com.myproject:restful:jar:4.1.5-SNAPSHOT:compile
[INFO] +- com.myproject:restful-common:jar:4.1.5-SNAPSHOT:compile
[INFO] | \- (commons-codec:commons-codec:jar:1.8:compile - omitted for conflict with 1.11)
[INFO] \- (commons-codec:commons-codec:jar:1.8:compile - omitted for conflict with 1.11)
如果我正确地读取了树,则将 commons-codec
依赖关系的其他版本(包括v1.8和v1.10)从类路径中省略,而转而使用v1.11,是我想要的.
If I'm reading the tree correctly, other versions of the commons-codec
dependency, including v1.8 and v1.10 are being ommitted from the classpath in favour of v1.11, which is what I want.
但是,如果我从依赖于microservices-common的项目的角度来看依赖树,则它看起来像这样:
However, if I pull the dependency tree from the perspective of my project that depends on microservices-common, it looks like this:
[INFO] com.myproject:microservice:jar:1.0-SNAPSHOT
[INFO] +- org.apache.httpcomponents:httpasyncclient:jar:4.1.3:compile
[INFO] | \- org.apache.httpcomponents:httpclient:jar:4.5.3:compile
[INFO] | \- (commons-codec:commons-codec:jar:1.10:compile - version managed from 1.11; omitted for duplicate)
[INFO] \- com.myproject:microservice-common:jar:1.0-SNAPSHOT:compile
[INFO] +- commons-codec:commons-codec:jar:1.10:compile
[INFO] \- com.myproject:restful:jar:4.1.5-SNAPSHOT:compile
[INFO] +- com.myproject:restful-common:jar:4.1.5-SNAPSHOT:compile
[INFO] | \- (commons-codec:commons-codec:jar:1.10:compile - version managed from 1.8; omitted for duplicate)
[INFO] \- (commons-codec:commons-codec:jar:1.10:compile - version managed from 1.8; omitted for duplicate)
在这棵树中,我看到消息从1.x版本管理;为重复而省略".我不确定这到底是什么意思,更令人担忧的是,第6行显示 commons-codec:1.10
是我的类路径的最终结果,而不是v1.11,这实际上是我的意思想要.
In this tree, I'm seeing the message "version managed from 1.x; omitted for duplicate". I'm not sure what that means exactly, and, more concerning, line 6 shows that commons-codec:1.10
is what's ending up on my classpath, rather than v1.11, which is what I actually want.
应注意, com.myproject:microservice-common:jar:1.0-SNAPSHOT
的 pom.xml
声明了 commons-codec:1.11
依赖项,因此 commons-codec:1.10
可能来自的唯一位置是 org.apache.httpcomponents:httpclient:jar:4.1.3
或 com.myproject:restful:jar:4.1.5-SNAPSHOT
(由于遗留原因我无法删除的另一个公共库),但目前尚不清楚我为什么选择了该传递依赖项的版本以包含在我的微服务公共库声明的版本中.
It should be noted that the pom.xml
for com.myproject:microservice-common:jar:1.0-SNAPSHOT
declares the commons-codec:1.11
dependency, so the only places that the commons-codec:1.10
could have come from is either org.apache.httpcomponents:httpclient:jar:4.1.3
or com.myproject:restful:jar:4.1.5-SNAPSHOT
(another common library that I can't get rid of for legacy reasons), but it's not clear to me why that version of the transitive dependency is being selected for inclusion over the version that my microservices-common library declares.
有人可以解释当依赖库中存在同一个库的多个版本时,依赖选择的工作原理,以及为什么在隔离构建时,常见的微服务似乎会选择传递依赖的正确版本,但是我的微服务项目选择了不同的方法版本是什么时候构建的?
Can anybody explain how dependency selection works when multiple versions of the same library exist in the dependency tree, and why microservices-common appears to select the correct version of the transitive dependency when built in isolation, but my microservices project selects a different version when I build it?
推荐答案
Maven在依赖关系树中选择最近的依赖关系版本. Maven文档:
Maven chooses the version of the dependency that is nearest in the dependency tree. This is explained very well in the Maven documentation:
最近定义"表示所使用的版本是最接近的版本一个到您的项目中的依赖树,例如.如果依赖A,B和C的A定义为A-> B-> C-> D 2.0和A-> E-> D1.0,则在构建A时将使用D 1.0,因为从A到D到E的路径更短.
"nearest definition" means that the version used will be the closest one to your project in the tree of dependencies, eg. if dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter.
如果依赖项在同一级别上多次出现,则第一个声明获胜(自Maven 2.0.9起).
If the dependency is occurring multiple times at the same level, the first declaration wins (since Maven 2.0.9).
确保使用所需版本的commons-codec的最佳且既定方法是在微服务" pom中(直接在 project
元素下)声明 dependencyManagement
:
The best and established way to ensure using the required version of commons-codec, is to declare dependencyManagement
in your 'microservice' pom (directly under the project
element):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
</dependencies>
</dependencyManagement>
此外,请确保您运行的是Maven的最新版本(建议使用3.5).
Also, make sure you run a recent version of Maven (3.5 recommended).
这篇关于当依赖树中存在两个或更多版本的依赖时,Maven如何选择传递依赖的版本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!