0%

maven间接依赖版本不一致

一、示例

我们的 pom.xml 文件具有以下依赖项,但不直接依赖于 spring-core。

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>

如上,我们遇到了一种情况,Maven 选择了一个不一致的间接依赖版本,想了解Maven在引入包时是如何做选择的,以及如何防止版本不一致导致的各种问题。

二、解析

1、两者都依赖于spring-core

spring-web 3.1.2.RELEASE 依赖于 spring-core 3.1.2.RELEASE(参见它的 pom-file)
spring-data-jpa 1.1.0.RELEASE 依赖于任意一个 3. x 版本的 spring-core(准确地说是 [3.0.7.RELEASE,4.0.0.RELEASE),参见它的 pom-file)。
结合两者,我希望 Maven 选择 spring-core 版本 3.1.2.RELEASE。然而,事实并非如此。相反,它从范围 [3.0.7.RELEASE,4.0.0.RELEASE) 中选择最高的,目前是 3.2.0.RELEASE。

2、重现场景

将上面的pom.xml文件放在自己的目录下,然后运行

1
mvn dependency:tree -Dverbose=true

在Linux上的Maven 2.2.1和Maven 3.0上得到了相同的结果。
在spring core 3.2.0.RC1可用时,就会遇到了这种情况。由于spring core 3.1和3.2之间的不兼容更改,构建发生了的错误。但是调整了依赖的顺序后就没那么幸运了,而且运行时错误很难追踪
声明的顺序很重要:如果我把 spring-web 放在第一位,那么会选择 spring-core 3.1.2.RELEASE

三、如何让 Maven 选择一致的间接依赖版本

如何让Maven选择一致的间接依赖版本,或者在maven做出的选择与pom文件中指定的版本不一致时发出警告?
对于这个特定的例子,可以通过在<dependencyManagement>中添加一个依赖项来获得正确的行为,指定我们总是希望spring-core 3.1.2.RELEASE。但是,如果Maven在没有这种特定声明的情况下如何做正确的选择

四、解答

这种期望的似乎合乎逻辑,但Maven不可能做到这一点。它只是在不知道spring-data-jpa可能与spring-core有什么关系的情况下解决依赖关系。
依赖项解析按照此处描述的方式工作,并且是你已经声明的方式:

依赖传递决定了当遇到多个版本的组件时,将使用哪个版本的依赖。
目前,Maven 2.0只支持使用“最近的定义”,这意味着它将使用依赖关系树中与项目最接近的依赖关系的版本。
你总是可以通过在项目的POM中明确声明版本来保证版本。
注意,如果两个依赖关系版本在依赖关系树中处于相同的深度,则在Maven 2.0.8之前,没有定义哪个版本会被选取,但从Maven 2.0.9开始,就会按照声明中的顺序抉择:第一个声明被选取。

所以我认为防止这种情况的唯一方法是意识到它的存在并在你自己的 pom.xml 中明确你需要的版本。
版本规范中 x.y只是使用此版本的建议。如果要强制使用此版本,则必须设置[x.y]。

五、相关

如何把本地jar包将引入到Maven项目中
创建maven父子工程
pom配置(依赖引用)
pom配置文件结构
搭建maven本地仓库