maven依赖插件忽略了依赖版本?

时间:2017-02-09 15:41:30

标签: java maven dependencies maven-dependency-plugin

在我看来,maven依赖插件在计算依赖列表时行为不端。

假设这3个项目:

BASE1:

<?xml version="1.0" encoding="UTF-8"?>                                                                                                                            
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>mygroup</groupId>
    <artifactId>base1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
      <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.3</version>
      </dependency>
    </dependencies>
</project>

BASE2:

<?xml version="1.0" encoding="UTF-8"?>                                                                                                                            
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>mygroup</groupId>
    <artifactId>base2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
      <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
      </dependency>
    </dependencies>
</project>

组合:

<?xml version="1.0" encoding="UTF-8"?>                                                                                                                            
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>mygroup</groupId>
    <artifactId>combined</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
      <dependency>
        <groupId>mygroup</groupId>
        <artifactId>base1</artifactId>
        <version>1.0-SNAPSHOT</version>
      </dependency>
      <dependency>
        <groupId>mygroup</groupId>
        <artifactId>base2</artifactId>
        <version>1.0-SNAPSHOT</version>
      </dependency>
    </dependencies>
</project>

base1和base2都依赖于commons-lang,但每个都在不同的版本上! 组合取决于base1和base2。

在组合上调用mvn dependency:list时,我希望在版本2.3和2.6中看到base1,base2和commons-lang,因为两者都被使用。 但实际输出是:

[INFO] The following files have been resolved:
[INFO]    commons-lang:commons-lang:jar:2.3:compile
[INFO]    mygroup:base1:jar:1.0-SNAPSHOT:compile
[INFO]    mygroup:base2:jar:1.0-SNAPSHOT:compile

它甚至没有使用版本号最高的普通版,而只是它首先找到的版本。

我该如何避免这种情况?我需要所有依赖项。

3 个答案:

答案 0 :(得分:3)

根据此official documentation(相关部分以粗体突出显示):

  

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

因此,Maven选择版本2.3,因为在依赖项解析过程中首先遇到它。请注意,如果您在// map an array of promises var deferreds = urllist.map(function(url){ // return the promise that `$.ajax` returns return $.ajax({ url: url, dataType: 'jsonp' }).then(function(data){ return data.value; }) }); $.when.apply($, deferreds).then(function(results){ // results will be array of each `data.value` in proper order var datalist = results; // now do whatever you were doing with original datalist $.each(datalist.... }).fail(function(){ // Probably want to catch failure }).always(function(){ // Or use always if you want to do the same thing // whether the call succeeds or fails }); 模块上运行mvn dependency:tree,它将显示使用的版本以及省略了哪个版本。

最好的解决方案是通过在其POM中声明依赖关系来明确选择combined工件中所需的版本,以便Maven比其他版本更喜欢它:

combined

请注意,Maven不能选择两个版本,因为在这种情况下,项目的类路径上会有两个相同类的定义,这可能会在运行时导致意外问题。

答案 1 :(得分:1)

Maven从上到下扫描pom并使用它遇到的第一个版本。

假设你真的需要两个版本的commons-lang,你可以将这两个版本放在你的项目中并使用maven将它们打包到你的jar中。

然而,编译器如何知道对StringUtils.isEmpty()的调用是否调用版本2.3或2.6?

Same discussion here

答案 2 :(得分:1)

Maven总是使用&#34;最近的胜利来解决冲突&#34;战略。您可以运行以下命令来查看使用特定版本的原因:

mvn dependency:tree -Dverbose -Dincludes=commons-lang

有关详情,请参阅以下内容: https://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html