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 中复制了相同的或者,您可以排除您不想要的依赖项。 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 的 </dependencies>
标签中放置的内容将包含在根 pom 的所有子模块中。如果您的所有模块都使用该依赖项,那么这就是要走的路。
但是,如果 10 个子模块中只有 3 个使用某些依赖项,则您不希望此依赖项包含在所有子模块中。在这种情况下,您可以将依赖项放在</dependencyManagement>
中。这将确保任何需要依赖项的子模块都必须在自己的 pom 文件中声明它,但它们将使用与 </dependencyManagement>
标记中指定的相同版本的依赖项。
您也可以使用</dependencyManagement>
来修改传递依赖中使用的版本,因为在最上面的 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:如何覆盖库添加的依赖项的主要内容,如果未能解决你的问题,请参考以下文章
无法从 Bndtools 中的 Maven 存储库添加测试依赖项