我正在开发一个大型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-a
出现时library-c:v1
,而module-b
会在library-b
出现library-c:v2
}}
问题在于module-a
和module-b
在部署module-c
时需要在同一个类路径上共存,但在{{1}时选择library-c
的任何版本打包后,至少有一个库组合没有经过单元测试!
我想以某种方式将module-c
的版本固定在父pom级别,而不是在每个过渡依赖于library-c
的模块中重复自己;理想情况下,它会以这样一种方式添加,表明如果library-c
和library-a
不再依赖它,它就会被允许消失的传递依赖。
我想保证只选择了一个版本
整个项目的每个传递依赖都源于这个父pom,如果这不是真的,我希望构建爆炸。我编写了一个工具来解析library-b
的输出(将树的叶子转换成从叶到根的路径林,然后找到具有依赖路径的所有不同版本的叶),这样我就可以看到问题,但是如果没有明确地解决每个冲突的传递依赖关系并且使用冗余声明来膨胀poms,这似乎并不富有成效。如果我别无选择,那就是我要做的事情。
使用Maven处理此传递依赖冲突问题的最佳方法是什么?
这个问题有多严重?除了获得令人难以置信的测试覆盖率之外,在实践中我看到JVM在运行时从部署的错误版本中查出mvn dependency:tree
。我希望至少在测试时看到这些。
答案 0 :(得分:2)
看起来有两个方面:
- 您需要坚持单一版本的依赖项,无论是明确声明还是可传递获取
醇>
您可以在此处使用<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
中声明这种依赖关系,您使用父级中声明的版本坚持使用两个子模块。
- 您希望保护自己免受未来发生的不愉快的依赖性添加
醇>
您可以在此使用Maven Enforcer plugin,特别是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>
可以将enforcer配置为在发现非收敛依赖关系时失败或发出警告。