maven 依赖冲突

依赖冲突

1、对于 Maven 而言,同一个 groupId 同一个 artifactId 下,只能使用一个 version。

复制代码
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.6.1</version>
        </dependency>
        <!-- 只会使用 3.6 这个版本的依赖 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.6</version>
        </dependency>

若相同类型但版本不同的依赖存在于同一个 pom 文件,只会引入后一个声明的依赖。

2、项目的两个依赖同时引入了某个依赖。

  • 最短路径优先(Nearest Definition Wins):即优先选择依赖树中离项目最近的版本。
  • 先声明者优先(First Declaration Wins) :即优先选择在 pom.xml 中首次声明的依赖版本。

举个例子,项目存在下面这样的依赖关系:

复制代码
依赖链路一:A -> B -> C -> X(1.0)
依赖链路二:A -> D -> X(2.0)

这两条依赖路径上有两个版本的 X,为了避免依赖重复,Maven 只会选择其中的一个进行解析。

哪个版本的 X 会被 Maven 解析使用呢?

Maven 在遇到这种问题的时候,会遵循 路径最短优先声明顺序优先 两大原则。解决这个问题的过程也被称为 Maven 依赖调解

最短路径优先:

复制代码
依赖链路一:A -> B -> C -> X(1.0) // dist = 3
依赖链路二:A -> D -> X(2.0) // dist = 2

依赖链路二的路径最短,因此,X(2.0)会被解析使用。

不过,你也可以发现。路径最短优先原则并不是通用的,像下面这种路径长度相等的情况就不能单单通过其解决了:

**先声明者优先:**举个例子,项目存在下面这样的依赖关系:

复制代码
依赖链路一:A -> B -> X(1.0)
依赖链路二:A -> D -> X(2.0)

这两条依赖路径上有两个版本的 X,为了避免依赖重复,Maven 只会选择其中的一个进行解析。

复制代码
<!-- A pom.xml -->
<dependencies>
    ...
    dependency B
    ...
    dependency D
</dependencies>

在依赖路径长度相等的前提下,在 pom.xml 中依赖声明的顺序决定了谁会被解析使用,顺序最前的那个依赖优胜。该例中,如果 B 的依赖声明在 D 之前,那么 X (1.0)就会被解析使用。

排除依赖

单纯依赖 Maven 来进行依赖调解,在很多情况下是不适用的,需要我们手动排除依赖。

举个例子,当前项目存在下面这样的依赖关系:

复制代码
依赖链路一:A -> B -> C -> X(1.5) // dist = 3
依赖链路二:A -> D -> X(1.0) // dist = 2

根据路径最短优先原则,X(1.0) 会被解析使用,也就是说实际用的是 1.0 版本的 X。

但是!这会一些问题:如果 D 依赖用到了 1.5 版本的 X 中才有的一个类,运行项目就会报NoClassDefFoundError错误。如果 D 依赖用到了 1.5 版本的 X 中才有的一个方法,运行项目就会报NoSuchMethodError错误。

现在知道为什么你的 Maven 项目总是会报NoClassDefFoundErrorNoSuchMethodError错误了吧?

如何解决呢? 我们可以通过exclusion标签手动将 X(1.0) 给排除。

复制代码
<dependency>
    ......
    <exclusions>
      <exclusion>
        <artifactId>x</artifactId>
        <groupId>org.apache.x</groupId>
      </exclusion>
    </exclusions>
</dependency>

一般在解决依赖冲突的时候,都会优先保留版本较高的。这是因为大部分 jar 在升级的时候都会做到向下兼容。

如果高版本修改了低版本的一些类或者方法的话,这个时候就能直接保留高版本了,而是应该考虑优化上层依赖,比如升级上层依赖的版本。

还是上面的例子:

复制代码
依赖链路一:A -> B -> C -> X(1.5) // dist = 3
依赖链路二:A -> D -> X(1.0) // dist = 2

保留了 1.5 版本的 X,但是这个版本的 X 删除了 1.0 版本中的某些类。这个时候,可以考虑升级 D 的版本到一个 X 兼容的版本。

更多消息资讯,请访问昂焱数据

相关推荐
6<73 分钟前
【go】静态类型与动态类型
开发语言·后端·golang
柚几哥哥3 分钟前
IntelliJ IDEA全栈Git指南:从零构建到高效协作开发
java·git·intellij-idea
技术liul8 分钟前
解决Spring Boot Configuration Annotation Processor not configured
java·spring boot·后端
chushiyunen20 分钟前
dom操作笔记、xml和document等
xml·java·笔记
whisperrr.20 分钟前
【spring01】Spring 管理 Bean-IOC,基于 XML 配置 bean
xml·java·spring
chushiyunen22 分钟前
tomcat使用笔记、启动失败但是未打印日志
java·笔记·tomcat
天上掉下来个程小白29 分钟前
HttpClient-03.入门案例-发送POST方式请求
java·spring·httpclient·苍穹外卖
ModestCoder_38 分钟前
将一个新的机器人模型导入最新版isaacLab进行训练(以unitree H1_2为例)
android·java·机器人
a180079310801 小时前
软件工程面试题(二十二)
java·面试·软件工程
RainbowSea1 小时前
4. RabbitMQ 发布确认的配置详细说明
java·消息队列·rabbitmq