【问题标题】:Why is it impossible to include multiple versions of the same dependency in Maven?为什么不能在 Maven 中包含同一依赖项的多个版本?
【发布时间】:2014-11-04 01:25:12
【问题描述】:

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

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

依赖中介 - 这决定了依赖的版本 当遇到工件的多个版本时将使用。 目前,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 的功能,那么我们将收到运行时错误(NoSuchMethodErrorClassNotFoundException 等),这不好。

所以要“修复”这个问题,我们可以从依赖项A 中排除依赖项X,以便使用X 2.0 版本。但是哦不! X 2.0 版不向后兼容,因此我们最终会从 A 获得运行时错误。

据我所知,Maven 无法正确解决此问题。您所能做的就是希望掌握其中一个库的源代码并自行修复。对吗?

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

【问题讨论】:

    标签: java maven shared-libraries


    【解决方案1】:

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

    我不确定是否有一个包罗万象的解决方案。如果您控制了AB,则可以使用shadingX 的用法重命名为不会发生冲突的名称,如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,或者在您的 POM 中明确列出 X

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-24
      • 1970-01-01
      • 2015-04-19
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 2022-07-18
      • 1970-01-01
      相关资源
      最近更新 更多