让Maven用最接近的可用匹配来解决缺少的依赖项

时间:2017-08-17 00:42:07

标签: maven dependency-management

当我查看我的本地Maven缓存(~/.m2/repository/)时,我看到了某些工件的10-20个版本,其中一些只用于一个特定的构建(项目)。我想摆脱这种重复(真的,它们是不同的版本,但我仍然认为依赖项目能够容忍微小版本或次版本)并以某种方式让Maven求助于最接近如果本地存储库中缺少特定工件版本,则在依赖项解析期间可用版本。

例如,如果我的本地缓存中有1.0.0个工件1.1.21.4.02.0.0foo:bar,我希望Maven到:

  • 使用1.1.2进行需要1.1.0
  • 的构建
  • 使用1.4.0进行需要1.4.10
  • 的构建
  • 使用2.0.0进行需要2.5.0
  • 的构建

无需手动更改特定版本的pom

我非常清楚在没有正确分析的情况下切换依赖版本所带来的风险,我只是要求一种机制用于非关键版本(例如我刚刚克隆的工具/库)一个VCS,并且想运行并试用),最好只在提供特定标志时激活。

是否存在某些内容,例如Maven扩展或插件(可以在系统范围内应用,并根据需要使用标记激活),这可以帮助我实现目标吗?

P.S。:自&#34;最接近&#34;的定义可能是模棱两可的(考虑到Maven可能不知道1.4.02.0.0中的哪一个更接近1.5.0,这取决于它们之间的实际发布版本),甚至可能就足够了我可以在构建命令上指定版本(例如mvn package -Dfoo:bar=1.4.0),仍然不进行任何手动pom更改。 (虽然对于已指定为<properties>条目的版本可能已经存在这种情况,但我想要一个通用解决方案,即使可以覆盖传递依赖项中的硬编码版本。)

P.P.S。:请注意,我要编写的项目不是由我创作/编写的,所以我对他们实际的pom文件没有真正的控制权。我正在寻找的是一种覆盖其pom文件中的依赖版本而无需在源级别进行任何手动修改的方法。

2 个答案:

答案 0 :(得分:1)

为了更改传递依赖关系,您需要在直接依赖关系中排除传递依赖关系,然后在您的pom中添加直接依赖关系。

例如,如果您依赖于foo.jar(取决于xyz.jar版本1.3)和bar.jar(依赖于xyz.jar版本1.4),那么您可以将这两个部分放在pom中:

<!-- Define the version(s) that you allow your dependencies to depend on. -->
<dependencyManagement>
  <dependency>
    <groupId>projectXyz</groupId>
    <artifactId>xyz</artifactId>
    <version>[1.0,2.0)</version>
  </dependency>
  <dependency>
    <groupId>projectFoo</groupId>
    <artifactId>foo</artifactId>
    <version>1</version>
    <exclusions>
      <exclusion>
        <groupId>projectXyz</groupId>
        <artifactId>xyz</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>projectBar</groupId>
    <artifactId>bar</artifactId>
    <version>5</version>
    <exclusions>
      <exclusion>
        <groupId>projectXyz</groupId>
        <artifactId>xyz</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
</dependencyManagement>
...
<!-- Declare your dependencies but don't allow them to suck in their transitive dependencies. -->
<dependencies>
  <dependency>
    <groupId>projectXyz</groupId>
    <artifactId>xyz</artifactId>
  </dependency>
  <dependency>
    <groupId>projectFoo</groupId>
    <artifactId>foo</artifactId>
  </dependency>
  <dependency>
    <groupId>projectBar</groupId>
    <artifactId>bar</artifactId>
  </dependency>
</dependencies>
...

这将获取它可以使用的最新版本的xyz.jar,这将是唯一使用的版本。当foo和bar使用xyz时,它们将具有您允许进入项目的版本。

最好的办法是使用parent pom(或bom:物料清单)与明确定义且维护良好的dependencyManagement部分。坚持使用单一版本的所有项目,只需在所有项目之间共享“一切”。如果需要,您可以覆盖项目中的版本。

如果您更愿意在每个项目中定义版本,那么version ranges将起作用。对于您给出的三个示例,您将使用以下内容:

  • [1.1.0,1.2)
  • [1.4.0,1.5)
  • [2.0.0,)

(这里可以修正。我近10年来没有使用版本范围。)

最后,为了让它使用已经可用的版本,而不是下载最好的版本,您所能做的就是使用local artifact repository作为中央maven存储库,turn off access to maven central and bintray。< / p>

答案 1 :(得分:0)

到目前为止我找到的最近的东西:https://github.com/jboss/maven-dependency-management-extension/blob/master/README.md

可以将其放入${MAVEN_HOME}/lib/ext并用于覆盖特定依赖项的版本,例如: mvn install -Dversion:junit:junit=4.10。虽然它没有提供建议的智能版本推导&#34;方法,这是一个足够好的解决方案。