Maven选择间接依赖的不一致版本:为什么,以及如何预防?

Mar*_*ica 5 dependency-management maven

我们遇到了Maven选择间接依赖的不一致版本的情况,我想了解为什么以及如何在将来防止这种情况.

我们的pom.xml文件具有以下依赖项:

<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>
Run Code Online (Sandbox Code Playgroud)

但没有直接依赖于spring-core.

两者都依赖于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文件).

结合两者,我希望Maven选择spring-core版本3.1.2.RELEASE.但事实并非如此.相反,它选择范围[3.0.7.RELEASE,4.0.0.RELEASE)中的最高值,目前为3.2.0.RELEASE.

(复制场景:将上面的pom.xml文件(gist)放在它自己的目录中,然后运行mvn dependency:tree -Dverbose=true:对我来说结果就是这个树(gist).我在Linux和Maven 3.0上得到了相同的结果. 4在Windows上.)

这似乎是错误的,因为它是不一致的:使用spring-web的pom文件不允许的spring-core版本.

(当spring-core 3.2.0.RC1可用时,我们就会发生这种情况:在下一次更新中它突然被选中,我们很幸运,由于spring-core 3.1和3.2之间的不兼容变化,我们遇到了构建错误.但是下次我们可能没有那么幸运,并且有很难追查的运行时错误.)

Urghh:我刚刚注意到的顺序<dependency>报关事宜:如果我把弹簧网,然后再弹簧核心3.1.2.RELEASE 选中.是什么赋予了?

问题:我们如何让Maven选择间接依赖的一致版本,或者至少警告它是否做出与pom文件中指定的版本相反的选择?

更新:我在这里要求一般解决方案.对于这个特定的情况,我知道我可以通过添加依赖项来获得正确的行为<dependencyManagement>,指定我总是想要spring-core 3.1.2.RELEASE.但是,我希望Maven在没有这些具体声明的情况下做Right Thing(TM).

FrV*_*aBe 7

您的期望似乎是逻辑,但Maven没有机会这样做.它只是在没有spring-data-jpa可能与之有关的知识的情况下解析依赖关系spring-core.

依赖项解析的工作方式与此处描述的一样,是您已经描述的方式:

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

所以我认为防止这种情况的唯一方法就是要注意它并在你自己的pom中明确地设置你需要的版本.

顺便说一句,为什么你认为" 这似乎是错误的,因为它是不一致的:使用spring-core的版本,弹簧网的pom文件不允许. "?

版本规范<version>x.y</version>只是推荐使用此版本(请参阅此处的 "注释" ).如果您打算强制使用此版本,则必须进行设置<version>[x.y]</version>.