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

Java 为什么在Maven中不可能包含同一依赖项的多个版本?,java,maven,shared-libraries,Java,Maven,Shared Libraries,假设一个用户正在编写一个具有2个依赖项的应用程序;让我们把它们称为dependencyA和dependencyB。您无法控制这些依赖项中的任何一个;它们不是您的库,但您的应用程序仍然依赖于它们。结果表明,依赖关系A与依赖关系X(版本1.0)有依赖关系;B依赖于X(版本2.0) 根据,依赖项中介将用于决定使用哪个依赖项: 依赖项中介-这决定了依赖项的版本 将在遇到工件的多个版本时使用。 目前,Maven 2.0仅支持使用“最近的定义” 这意味着它将使用最接近的依赖项的版本 您的项目位于依赖关系树中

假设一个用户正在编写一个具有2个依赖项的应用程序;让我们把它们称为dependency
A
和dependency
B
。您无法控制这些依赖项中的任何一个;它们不是您的库,但您的应用程序仍然依赖于它们。结果表明,依赖关系
A
与依赖关系
X
(版本1.0)有依赖关系;B依赖于
X
(版本2.0)

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

依赖项中介-这决定了依赖项的版本 将在遇到工件的多个版本时使用。 目前,Maven 2.0仅支持使用“最近的定义” 这意味着它将使用最接近的依赖项的版本 您的项目位于依赖关系树中。你总是可以保证 通过在项目的POM中显式声明它来创建版本。注意,如果 两个依赖项版本在依赖项树中的深度相同, 在Maven 2.0.8之前,还没有定义哪一个会赢,但从那时起 Maven 2.0.9重要的是声明中的顺序:第一个 宣言获胜

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

因此,为了“修复”这个问题,我们可以将依赖项
X
从依赖项
A
中排除,从而使用
X
版本2.0。但是,哦,不
X
Version2.0不向后兼容,因此我们最终从
A
中得到运行时错误

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


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

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

我不确定是否有一个包罗万象的解决办法。如果控制了
A
B
,则可以使用着色将
X
的用法重命名为不会冲突的名称,如中所述

一般来说,我们必须希望在库之间保持向后兼容性,并测试生成的应用程序,以确保没有问题。显然,您希望将Maven配置为包含
x-2.0
而不是
x-1.0
,方法是首先列出
B
,或者在POM中明确列出
x

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