如何让Maven警告任意版本的选择?

时间:2013-01-24 13:07:32

标签: maven dependency-management

在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警告我们?

1 个答案:

答案 0 :(得分:2)

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

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

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

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>
    

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

  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>
    
  3. 在其中的两个中,我更喜欢后者,因为它至少会让人们暗示为什么明确提到这些依赖。

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

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

    据我所知,目前没有任何执法者规则支持验证您的要求。

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

    该规则应执行以下操作:

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

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