Maven:如何覆盖库添加的依赖项

Posted

技术标签:

【中文标题】Maven:如何覆盖库添加的依赖项【英文标题】:Maven: how to override the dependency added by a library 【发布时间】:2011-04-25 15:08:22 【问题描述】:

这是我的一般问题:

我的项目 P 依赖于 A 依赖于 B 依赖于 C 依赖于 D 的 1.0.1 版本。

D 的 1.0.1 版本有问题,我想强制使用另一个模块。我不知道如何在我的项目的 POM 中声明它,因为我没有直接添加对 D 的依赖。是 C 声明了对 D 的依赖。

重要提示:在这种情况下,不仅版本发生了变化,而且组和工件也发生了变化。所以这不仅仅是覆盖依赖版本的问题,而是排除一个模块并包含另一个模块的问题。

在具体情况下,D 是 StAX,其 1.0.1 有一个bug。根据错误中的注释,“通过将 stax-api-1.0.1 (maven GroupId = stax) 替换为 stax-api-1.0-2 (maven GroupId = javax.xml.stream)”解决了问题,所以我正在尝试。

因此,D = stax:stax-api:jar:1.0.1 和 C = org.apache.xmlbeans:xmlbeans:jar:2.3.0

我正在使用 maven 2.0.9 以防万一。

mvn 依赖的输出:tree"

mvn dependency:tree
[..snip..]
[INFO] +- org.apache.poi:poi-ooxml:jar:3.6:compile
[INFO] |  +- org.apache.poi:poi-ooxml-schemas:jar:3.6:compile
[INFO] |  |  +- org.apache.xmlbeans:xmlbeans:jar:2.3.0:compile
[INFO] |  |  |  \- stax:stax-api:jar:1.0.1:compile

在我项目的 POM 中,我对“A”有以下依赖:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.6</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.6</version>
</dependency>

提前致谢。

【问题讨论】:

【参考方案1】:

只需在当前 pom.xml 中指定版本即可。此处指定的版本将覆盖其他版本。

强制一个版本 如果在当前 POM 中以特定版本声明某个版本,则该版本将始终受到尊重 - 但是,应该注意,如果它本身依赖于使用传递依赖项,这也会影响下游的其他 pom。


资源:

Dependency Mediation and Conflict Resolution Introduction to the Dependency Mechanism

【讨论】:

不清楚如何指定版本,因为我没有声明对 D 的依赖。此外,您提供的第一个链接有“本文档描述了依赖管理的其余要求尚未为 Maven 2.0 实现,尤其是在传递依赖方面。”在顶部。 @wishihadabettername,正如其他文档中所说:“您可以在 A 中显式添加对 D 2.0 的依赖项以强制使用 D 2.0” 您实际上在自己的 pom.xml 中复制了相同的 条目。在您的依赖项中,指定您想要的 。这将覆盖“更深”依赖项使用的任何版本。【参考方案2】:

或者,您可以排除您不想要的依赖项。 STAX 包含在 JDK 1.6 中,因此如果您使用的是 1.6,则可以完全排除它。

下面的示例对您来说有点错误 - 您只需要两个排除项之一,但我不太确定哪一个。还有其他版本的 Stax 浮动,在下面的示例中,我导入了 A 导入了 B 导入了 C 和 D ,每个(通过更多的传递依赖项)导入了不同版本的 Stax。因此,在我对“A”的依赖中,我排除了两个版本的 Stax。

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

【讨论】:

需要注意的是,这种传递依赖是可以使用的,如果需要,排除会导致构建失败。 如果您使用的是现代 JDK(即 1.6+)并且您需要通过传递依赖包含的旧版本的 stax,您可能会遇到各种可怕的运行时类加载器问题.我的建议:使用 JDK 中的那个。如果您遇到“构建失败”,则您依赖于某种形式的古老 API,应该升级。或者:将 JDK 回滚到 1.5。祝你好运。【参考方案3】:

您在根 pom 的 &lt;/dependencies&gt; 标签中放置的内容将包含在根 pom 的所有子模块中。如果您的所有模块都使用该依赖项,那么这就是要走的路。

但是,如果 10 个子模块中只有 3 个使用某些依赖项,则您不希望此依赖项包含在所有子模块中。在这种情况下,您可以将依赖项放在&lt;/dependencyManagement&gt; 中。这将确保任何需要依赖项的子模块都必须在自己的 pom 文件中声明它,但它们将使用与 &lt;/dependencyManagement&gt; 标记中指定的相同版本的依赖项。

您也可以使用&lt;/dependencyManagement&gt; 来修改传递依赖中使用的版本,因为在最上面的 pom 文件中声明的版本就是将要使用的版本。如果您的项目 A 包含一个包含另一个外部项目 C v1.0 的外部项目 B v1.0,这将很有用。有时会在项目 C v1.0 中发现安全漏洞,在 v1.1 中已更正,但 B 的开发人员更新项目以使用 C 的 v1.1 的速度很慢。在这种情况下,您可以简单地声明在项目的根 pom 中依赖于 C v1.1,一切都会好起来的(假设 B v1.0 仍然能够使用 C v1.1 编译)。

【讨论】:

使用带有 Spring Boot 父级的 Kotlin 依赖项,dependencyManagement 方法(在顶层)是唯一有效的解决方案 这是正确的答案。您不希望这些库使您的 POM 变得混乱,除非您知道您将继续将它们作为传递依赖项永远存在。【参考方案4】:

我在否决第三方库中的依赖项时也遇到了麻烦。我使用 scot's approach 排除但我还在 pom.xml 中添加了具有较新版本的依赖项。 (我用的是 Maven 3.3.3)

所以对于 stAX 示例,它看起来像这样:

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

<dependency>
    <groupId>javax.xml.stream</groupId>
    <artifactId>stax-api</artifactId>
    <version>1.0-2</version>
</dependency>

【讨论】:

【参考方案5】:

接受的答案是正确的,但我想加两分钱。我遇到了一个问题,我有一个项目 A 有一个项目 B 作为依赖项。两个项目都使用 slf4j,但项目 B 使用 log4j,而项目 A 使用 logback。 项目 B 使用 slf4j 1.6.1,而项目 A 使用 slf4j 1.7.5(由于已经包含 logback 1.2.3 依赖项)。

问题: 项目 A 找不到 slf4j 1.7.5 上存在的函数,在检查了 eclip 的依赖层次选项卡后,我发现在构建期间它使用的是项目中的 slf4j 1.6.1 B、不使用logback的slf4j 1.7.5。

我通过更改项目 A pom 的依赖关系的顺序解决了这个问题,当我将项目 B 条目移到 logback 条目下方时,maven 开始使用 slf4j 1.7.5 构建项目。

编辑: 在项目 B 依赖项之前添加 slf4j 1.7.5 依赖项也可以。

【讨论】:

以上是关于Maven:如何覆盖库添加的依赖项的主要内容,如果未能解决你的问题,请参考以下文章

添加 GitLab 私有存储库作为 Maven 依赖项

无法从 Bndtools 中的 Maven 存储库添加测试依赖项

从 GitHub 加载 Maven 依赖项 [重复]

有没有办法可以使用Maven存储库为Ant添加依赖项?

如何从 lib 文件夹中添加 Maven 依赖 jar 文件

如何在 Maven 中为依赖项指定存储库