在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警告我们?
答案 0 :(得分:2)
正如您所发现的,版本范围是邪恶的。
真正的问题是版本范围是一个警报器,诱使人们认为他们是个好主意。
版本范围应该被视为开发人员的一个提示,允许开发人员从一组版本中选择他们想要的版本。
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-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>
个依赖项。
至于上述内容,但首先在依赖项中添加排除项更安全,例如
<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
我不记得是否有工具可以检查<exclusions>
是否实际上排除了任何传递依赖项,因此您可能需要对此进行调查。