如何跨多 pom Maven 项目固定传递依赖版本
How to pin transitive dependency versions across multi-pom Maven project
我正在开发一个大型 Java 代码库,该代码库分为多个模块,每个模块都有一个单独的 pom.xml,所有模块都由顶级 pom.xml.
我目前正在引入几个库依赖项。可传递的依赖集很大,幸运的是,不同模块的依赖版本存在冲突。
这是我的情况的简化:
project/pom.xml
/module-a/pom.xml # references library-a, depends on library-c:v1
/module-b/pom.xml # references library-b, depends on library-c:v2
/module-c/pom.xml # references module-a and module-b
现在 module-a
的单元测试将在 library-c:v1
存在的情况下执行 library-a
,而 module-b
将在 library-b
存在的情况下执行 library-b
=16=].
问题在于部署 module-c
时 module-a
和 module-b
需要在同一个类路径上共存,但是当 library-c
选择哪个版本时 module-c
被打包,至少有一个组合库没有经过单元测试!
我想以某种方式将 library-c
的版本固定在父 pom 级别,而不是在每个传递依赖于 library-c
的模块中重复我自己;理想情况下,它会以这样一种方式添加,表明它是允许消失的传递依赖,如果 library-a
和 library-b
不再依赖它。
我想保证只选择了一个版本
整个项目中的每一个传递依赖都源于这个父 pom,如果这不是真的,我希望构建崩溃。我写了一个工具来解析 mvn dependency:tree
的输出(将树的叶子变成从叶子到根的路径森林,然后用依赖路径找到所有不同版本的叶子)所以我可以看到问题,但是如果没有明确解决每个冲突的传递依赖关系并用冗余声明膨胀 poms,这似乎没有成果。万不得已,我自然会这么做。
用 Maven 处理这个传递依赖冲突问题的最佳方法是什么?
这个问题有多严重?除了获得令人信服的测试覆盖率之外,在实践中,我看到 JVM 在运行时因部署错误的版本而被杀死 NoSuchMethodError
。我宁愿至少在测试时看到这些。
看起来这有两个方面:
- You need to insist on a single version of a dependency, whether it is declared explicitly or acquired transitively
你可以在这里使用<dependencyManagement/>
。例如在顶层 pom.xml 你可以固定 library-c
:
的版本
<dependencyManagement>
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>library-c</artifactId>
<version>2</version>
<dependency>
<dependencies>
<dependencyManagement>
然后在 library-a
、library-b
中声明对 library-c
的依赖,如下所示:
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>library-c</artifactId>
<dependency>
<dependencies>
通过在父模块 dependencyManagement
中声明此依赖关系,您坚持要求两个子模块都使用在父模块中声明的版本。
- You want to protect yourself from unhappy dependency additions occurring in future
您可以使用 Maven Enforcer plugin here, specifically the dependencyConvergence 规则。例如:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
强制执行器可以配置为在发现非收敛依赖项时失败或发出警告。
我正在开发一个大型 Java 代码库,该代码库分为多个模块,每个模块都有一个单独的 pom.xml,所有模块都由顶级 pom.xml.
我目前正在引入几个库依赖项。可传递的依赖集很大,幸运的是,不同模块的依赖版本存在冲突。
这是我的情况的简化:
project/pom.xml
/module-a/pom.xml # references library-a, depends on library-c:v1
/module-b/pom.xml # references library-b, depends on library-c:v2
/module-c/pom.xml # references module-a and module-b
现在 module-a
的单元测试将在 library-c:v1
存在的情况下执行 library-a
,而 module-b
将在 library-b
存在的情况下执行 library-b
=16=].
问题在于部署 module-c
时 module-a
和 module-b
需要在同一个类路径上共存,但是当 library-c
选择哪个版本时 module-c
被打包,至少有一个组合库没有经过单元测试!
我想以某种方式将 library-c
的版本固定在父 pom 级别,而不是在每个传递依赖于 library-c
的模块中重复我自己;理想情况下,它会以这样一种方式添加,表明它是允许消失的传递依赖,如果 library-a
和 library-b
不再依赖它。
我想保证只选择了一个版本
整个项目中的每一个传递依赖都源于这个父 pom,如果这不是真的,我希望构建崩溃。我写了一个工具来解析 mvn dependency:tree
的输出(将树的叶子变成从叶子到根的路径森林,然后用依赖路径找到所有不同版本的叶子)所以我可以看到问题,但是如果没有明确解决每个冲突的传递依赖关系并用冗余声明膨胀 poms,这似乎没有成果。万不得已,我自然会这么做。
用 Maven 处理这个传递依赖冲突问题的最佳方法是什么?
这个问题有多严重?除了获得令人信服的测试覆盖率之外,在实践中,我看到 JVM 在运行时因部署错误的版本而被杀死 NoSuchMethodError
。我宁愿至少在测试时看到这些。
看起来这有两个方面:
- You need to insist on a single version of a dependency, whether it is declared explicitly or acquired transitively
你可以在这里使用<dependencyManagement/>
。例如在顶层 pom.xml 你可以固定 library-c
:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>library-c</artifactId>
<version>2</version>
<dependency>
<dependencies>
<dependencyManagement>
然后在 library-a
、library-b
中声明对 library-c
的依赖,如下所示:
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>library-c</artifactId>
<dependency>
<dependencies>
通过在父模块 dependencyManagement
中声明此依赖关系,您坚持要求两个子模块都使用在父模块中声明的版本。
- You want to protect yourself from unhappy dependency additions occurring in future
您可以使用 Maven Enforcer plugin here, specifically the dependencyConvergence 规则。例如:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
强制执行器可以配置为在发现非收敛依赖项时失败或发出警告。