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

标签 java maven shared-libraries

假设 a 正在编写一个具有 2 个依赖项的应用程序;让我们将它们称为依赖项A 和依赖项B。您无法控制其中任何一个依赖项;它们不是您的库,但您的应用程序仍然依赖于它们。事实证明,依赖项 A 依赖于依赖项 X(版本 1.0); B 依赖于 X(版本 2.0)。

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

Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, until Maven 2.0.8 it was not defined which one would win, but since Maven 2.0.9 it's the order in the declaration that counts: the first declaration wins.

因此,假设我们首先声明依赖项 A,然后 X 版本 1.0 将在我们的应用程序中使用。这意味着依赖项 B 将在运行时使用 X 版本 1.0,而 as 是针对 X 版本 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 允许您拥有同一 Artifact 的多个版本,那么毫无疑问会发生这种情况。所以这是 Maven 正在解决的 Java 问题。

我不确定是否有一个万能的解决方案。如果您控制了 AB,您可以使用阴影X 的用法重命名为不会出现的名称。 t 冲突,如 What is the maven-shade-plugin used for, and why would you want to relocate java packages? 中所述。

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

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

关于java - 为什么不可能在 Maven 中包含同一依赖项的多个版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25764687/

相关文章:

java - 如何在SWT中按ENTER设置遍历顺序

java - 错误 : diamond operator is not supported in -source1. 5

java - 如何解决上下文初始化失败的问题?

java - 为什么JVM在进入无限递归时不会崩溃?

java - Spring boot测试如何使用不同的application.properties进行集成测试

java - 可以保存到文件的JTable

java - 如何使用 Spring Data JPA 更新实体中的集合字段?

java - 如何使依赖于某个 jar 的 Jenkins 构建失败

c++ - 将单例实例共享到共享库而不导出它

Android原生库共享内存