【问题标题】:Different scopes of the same artifact and transitive dependencies issue同一工件的不同范围和传递依赖问题
【发布时间】:2012-01-19 09:37:32
【问题描述】:

我有一个项目 A,它使用库 L v1.0.0 和测试范围。项目 A 还依赖于项目 B(使用范围编译),而 B 可传递地依赖于库 L v1.0.0(使用范围编译)。

为什么项目 A 的库 L 的最终范围是“测试”?它在运行时导致我 NotClassDefFoundError 。似乎项目 A 对库 L 的依赖定义覆盖了对 L 的传递依赖。

这里有什么问题?我的项目 A 仅将 L 用于单元测试,因此我使用“测试”范围定义依赖项。但是,最后,我希望 L 在我的类路径中,因为项目 A 依赖项目 B 进行生产,而 B 需要(传递地)库 L。

谢谢你帮助我

【问题讨论】:

    标签: java maven maven-3


    【解决方案1】:

    你在使用 Maven 吗?在这种情况下,如果我没记错的话,Maven 将使用“最近”定义来确定实际范围。在这种情况下,模块 A 指定 test 并且 B 的传递范围被覆盖,因为 A 是最近的,因为您实际上在 A :) 当您有多个模块之间存在依赖关系时,这会变得更加复杂。 一种常见的解决方法是在 <dependencyManagement> 标记的公共父 Pom.xml 中定义所有依赖项(以及范围和版本)。

    【讨论】:

    • 标签是''。您编写了它,但它没有显示在某些浏览器上。我没有其他要添加到您的答案的内容,因此无法对其进行编辑。 (最少更改 6 个字符。)
    • 即使我在公共父 POM 中声明对 L(具有编译范围)的依赖关系,如果在 A 的 POM 中声明的对 L 的依赖具有“测试”范围,最终范围仍保持“范围” '。我看到您可以使用这种方式强制使用特殊版本但不能使用特殊范围。我目前看到的唯一解决方案是 UrsReupke。
    • 您不需要设置范围以在 A 中进行测试,因为这将是编译的,并且此测试也是 :)。 Maven的行为是这样的,我们必须接受它并采取相应的行动,我自己不是一个大粉丝:)
    【解决方案2】:

    作为 Peter 建议的替代方案,只需将 L 排除在 A 的依赖项之外。无论如何您都应该能够访问它,Maven 会将其视为 compile-scoped 依赖项。

    不过,这隐藏了 A 的测试依赖于 L。

    【讨论】:

    • 我知道有一些像这样的技巧(这就是我现在使用的),但我不明白为什么这不会自动包含在“编译”范围内。有解释还是缺少功能?
    • 它允许您明确说明您所追求的范围。可能是在运行时系统上“提供”了 L,所以 A 只需要它来进行测试。 IMO,缺少的(对于您的情况)是独立指定测试和生产范围的功能。
    • 但是 Maven 知道在项目 B 的路径上(在依赖关系树中),对 L 的依赖具有编译范围。为什么它不能决定 L 是这里编译所必需的?这似乎是一个错误......我的项目 A 使用 L 进行单元测试,但是在具有编译范围的 L 上存在传递依赖关系,我可以推断出最终范围必须是编译的,因为我需要它在我的路径上。
    • 是的,它可以——但接下来的人会提出相反的问题:“为什么 maven 将 L 添加到类路径中?我明确告诉它我只需要它来进行测试。”无论是否存在错误,Maven 都会对您的需求做出非常强烈的假设,并做出相应的行为。不要误会我的意思,我远不是一个 Maven 传道者——我只是接受了它的本来面目(如果情况允许,我会继续使用 Gradle。)
    • 我不知道在这种情况下为什么要让 Maven 选择测试依赖项,它的编译依赖项之一依赖于 L,所以他在类路径上需要 L。所以,我的想法是,除非有人找到相反的用例,否则这种假设是错误的。
    猜你喜欢
    • 2019-08-23
    • 2018-05-19
    • 2016-12-01
    • 2019-02-25
    • 2017-01-15
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    相关资源
    最近更新 更多