【问题标题】:How to make Maven warn about an arbitrary version choice?如何让 Maven 警告任意版本选择?
【发布时间】:2013-01-08 06:04:01
【问题描述】:

在一个 Maven 项目中,我们使用了第三方工件(特别是 spring-data-jpa 1.1.0.RELEASE),它依赖于另一个工件(spring-core),允许范围内的任何版本(准确地说:[ 3.0.7.RELEASE、4.0.0.RELEASE),见its pom-file)。我们没有直接依赖 spring-core。

所以有一天我们的构建选择了 3.1.2.RELEASE,但是当 3.2.0.RC1 发布时,我们的构建突然选择了那个版本。

但是,我们希望有可重复的构建:当我们在一年的时间内交付补丁时,我们不想引入更新版本的 spring-core 或任何其他间接依赖,至少不知道。

(我知道我们可以指导Maven为spring-core选择一个特定的版本,例如使用<dependencyManagement>,但我这里的意思是间接依赖中可能隐藏着任意选择,我喜欢Maven告诉我们这些,而无需定期手动检查。)

问题:如果 Maven 为任何间接依赖项做出任意版本选择,我们如何让 Maven 警告我们?

【问题讨论】:

标签: maven dependency-management


【解决方案1】:

正如您所发现的,版本范围是邪恶的。

真正的问题是版本范围是一个警笛,会诱使人们认为他们是个好主意。

版本范围确实应该被视为对开发人员的提示,允许开发人员从一组版本中选择他们想要的版本。

Maven 中的错误在于,首先允许在 pom.xml 中定义版本范围,因为这允许人们发布其中包含版本范围的工件。

一旦您对具有使用版本范围的传递依赖项的工件产生依赖项,实际上只有两种方法可以解决您的构建问题(一种只是第二种的更花哨的版本)

  1. 在传递依赖项上添加您自己的依赖项,但使用固定版本代替范围...例如

    <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-orm</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>3.1.2.RELEASE</version>
      <exclusions>
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    

    您不需要列出 &lt;optional&gt;true&lt;/optional&gt; 依赖项,因为它们不具有传递性,同样出于同样的原因,您也不需要列出 &lt;scope&gt;provided&lt;/scope&gt; 依赖项。

  2. 至于上述,但首先通过将排除项添加到依赖项来更安全,例如

    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.1.0.RELEASE</version>
      <exclusions>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-orm</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>3.1.2.RELEASE</version>
      <exclusions>
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    

在这两个中,我更喜欢后者,因为它至少可以提示人们为什么要明确提及这些依赖项。

所以回到你原来的问题,重点是当你在pom.xml 中添加或更新依赖项时,你需要设置这个依赖关系树。

如果spring-data-jpa:1.1.1.RELEASE 有一个完全不同的传递依赖树和不同的坐标,那么当您编辑pom.xml 以更新版本时,您也应该修复传递。

据我所知,目前没有任何强制执行规则来支持验证您的要求。

我建议编写一个执行者规则,我称之为:ensureTransitiveVersionRangesArePinned

该规则应执行以下操作:

  • 扫描项目依赖列表
  • 计算每个项目依赖提供的传递依赖
  • 如果这些传递依赖中的任何一个是版本范围,那么
    • 验证该传递依赖是否存在exclusion
    • 验证是否存在作为直接项目依赖项的传递依赖项的固定版本(如果没有固定版本,则可能不会失败,因为您可能正在添加位于不同 GAV 的等效工件,或者您可以不需要依赖项)...在任何情况下,如果没有重新添加依赖项,单元测试很可能应该通过触发 CNFE 来捕获它,所以这个检查可能不是严格要求的,但它可能应该打印一个警告。

我不记得是否有工具可以检查 &lt;exclusions&gt; 是否实际上排除了任何传递依赖项,因此您可能需要对此进行调查。

【讨论】:

  • tl;dr,但前两句 +1
猜你喜欢
  • 2012-10-11
  • 2021-05-09
  • 2021-04-08
  • 1970-01-01
  • 2015-04-13
  • 2013-10-20
  • 2017-04-14
  • 1970-01-01
  • 2011-01-02
相关资源
最近更新 更多