为什么不可能在Maven中包含同一依赖项的多个版本



想象一个正在编写的应用程序有2个依赖项;让我们称它们为依赖CCD_ 1和依赖B。您无法控制这两个依赖项中的任何一个;它们不是您的库,但您的应用程序仍然依赖于它们。结果表明,依赖A与依赖X(1.0版)存在依赖关系;并且B对CCD_ 5(版本2.0)具有依赖性

根据Maven文档,依赖中介将用于决定使用哪个依赖:

依赖关系中介-它确定依赖关系的版本将在遇到工件的多个版本时使用。目前,Maven 2.0只支持使用"最接近的定义"这意味着它将使用与依赖项树中的项目。你总是可以保证版本,方法是在项目的POM中明确声明它。请注意,如果两个依赖版本在依赖树中处于相同深度,在Maven 2.0.8之前,还没有确定哪一个会赢,但由于Maven 2.0.9重要的是声明中的顺序:第一个声明获胜。

因此,假设我们首先声明依赖项A,那么X 1.0版将在我们的应用程序中使用。这意味着依赖B将在运行时使用X版本1.0,其中as是针对A0版本2.0编译的。如果B使用一些仅2.0的功能,那么我们将得到一个运行时错误(NoSuchMethodErrorClassNotFoundException等),这是不好的。

因此,为了"修复"这一问题,我们可以从依赖A中排除依赖X,从而使用X 2.0版本。但是,哦,不!X 2.0版本不向后兼容,因此我们最终会从A中得到运行时错误。

据我所知,Maven没有办法妥善解决这个问题。您所能做的就是希望获得其中一个库的源代码并自行修复。这是正确的吗?

为什么X的两个版本都不可能打包到我的应用程序中,比如A使用X版本1.0,B使用X版本2.0,而我的应用中可用的X版本是Maven通过依赖中介选择的。这是Java的限制,还是Maven的限制?这种情况常见吗?还有其他可能的解决方案吗?所有库都应该保证向后兼容性以避免这个问题吗?

不能将具有相同名称的两个类加载到一个类加载程序中。如果Maven允许您拥有同一工件的多个版本,这无疑会发生。因此,这是Maven能够解决的Java问题。

我不确定是否有一个包罗万象的解决方案。如果您控制了AB,您可以使用着色X的使用重命名为不会发生冲突的内容,如maven着色插件的用途是什么,以及为什么要重新定位java包?中所述?。

一般来说,人们必须希望在库之间保持向后兼容性,并对生成的应用程序进行良好的测试,以确保没有问题。显然,您希望通过首先列出B或在POM中显式列出X来将Maven配置为包括x-2.0而不是x-1.0

警告:大多数版本命名方案都允许在1.x.x和2.x.x之间进行中断更改,因此您可能会遇到问题。一些Maven项目(如ApacheCommonsLang)在更改主要版本时会使用新的工件ID和包结构,以避免这些冲突。

最新更新