当依赖树中存在两个或多个版本的传递依赖时,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 的库。微服务公共库又依赖于 commons-codec:1.11。但是,当我尝试在我的项目中使用 microservices-common 时,commons-codec:1.10 最终出现在我的类路径中,并且我的代码无法编译,因为 microservices-common 正在尝试使用添加的 org.apache.commons.codec.digest.DigestUtils 构造函数commons-codec:1.11,但不存在于 commons-codec:1.10

这是微服务通用依赖关系树的相关部分:

[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,这就是我想要。

但是,如果我从我依赖microservices-common的项目的角度拉取依赖树,它是这样的:

[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)

在这棵树中,我看到了消息 "version managed from 1.x; omitted for duplicate"。我不确定这到底是什么意思,更重要的是,第 6 行显示 commons-codec:1.10 是我的类路径中的结尾,而不是我真正想要的 v1.11。

需要注意的是 pom.xml for com.myproject:microservice-common:jar:1.0-SNAPSHOT 声明了 commons-codec:1.11 依赖,所以 commons-codec:1.10 唯一可以 来自 org.apache.httpcomponents:httpclient:jar:4.1.3com.myproject:restful:jar:4.1.5-SNAPSHOT (另一个我由于遗留原因无法摆脱的公共库),但我不清楚为什么那个版本的传递依赖是正在 select 编辑以包含在我的微服务公共库声明的版本中。

任何人都可以解释当依赖树中存在同一个库的多个版本时依赖 selection 是如何工作的,以及为什么 microservices-common 在 select 传递依赖的正确版本独立构建,但我的微服务项目select构建时版本不同?

Maven 选择依赖关系树中最近 的依赖关系版本。这在 Maven documentation:

中有很好的解释

"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 起)。

确保使用所需版本的 commons-codec 的最佳和既定方法是在 'microservice' pom 中声明 dependencyManagement(直接在 project 元素下):

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.11</version>
        </dependency>
    </dependencies>
</dependencyManagement>

此外,请确保您 运行 使用最新版本的 Maven(推荐 3.5)。