maven依赖选择策略(依赖调解)

news2025/1/11 23:58:23

这里先抛出结论

  • 最短路径原则: 不同级依赖, 选择路径最短(对于传递性依赖和一级依赖)
  • 声明优先原则 : 同级依赖,先声明的覆盖后声明的(对于传递性依赖)
  • 同级依赖后加载覆盖先加载原则(不属于传递性依赖的情况,就是pom里的一级依赖)

我们都知道maven具有传递性依赖的机制,就是当你在pom中引用依赖A时,如果这个依赖A同时依赖B的话,那么maven会自动引入B的依赖,以传递性依赖的形式引入到项目中。

虽然这样做很方便,但是有时也会导致一些问题的产生,比如依赖冲突。
A -> C -> X(1.0)
B -> D -> X(2.0)
如果你在项目中引入了A和B,那么最终哪个依赖会被解析呢?按照上面写出的结论,其实是X(1.0)会被解析,你可能会想,既然maven已经按照规则帮我们选定了依赖,为什么会出现依赖冲突的情况呢?我们举个例子

1、你想如果依赖B的代码中引用了X(2.0)的新创建的类,但因为最终被解析的是X(1.0),所以运行时就会出现很典型的NoClassDefFoundError或ClassNotFoundException依赖冲突报错。
2、如果依赖B的代码中引用X(2.0)的新创建的方法,但因为最终被解析的是X(1.0),所以就会抛出 NoSuchMethodError系统异常。

所以还是得具体情况具体分析,如果我们手动排除依赖X(1.0),引入X(2.0)就不会出现问题了吗?也不一定的,有可能2.0版本的依赖删去了1.0版本中的一些方法和类,这种情况下同样会导致这些问题。

如何知道传递性依赖究竟是从哪条依赖中被引入的?

我们可以通过mvn dependency:tree命令来进行查看,如下图,我在pom文件中引入了两个版本的easyExcel的依赖,由于它们属于一级依赖,按照规则,应该引入后加载的版本
在这里插入图片描述
打开pom.xml所在文件夹,打开cmd命令行,输入mvn dependency:tree,我们可以从图片中看到,引入的确实是2.1.6版本的依赖
在这里插入图片描述

这里再举几个例子,我们进入2.1.6版本的easyexcel依赖中可以看到,该依赖还依赖于slf4j-api-1.7.26的依赖,这里我从中央仓库拿了一份其他版本的slf4j的依赖进行引入,我们刷新pom文件后再看看最终引入的slf4j究竟是什么版本的
重新引入其他版本的slf4j
其实由于上面的结论我们已经知道,最终引入的是1.7.30版本的slf4j-api,因为它们属于不同级的依赖,maven会按照最短路径进行引入
在这里插入图片描述
这里我抛出一个问题,如果slf4j-api-1.7.30版本的依赖比slf4j-api-1.7.26多出了一些新方法和类(这里只是举个例子,假设),并且在项目中我不是直接引入的slf4j-api-1.7.30版本,而是通过传递性依赖的方式引入,比如我引入了A依赖,A->依赖于slf4j-api-1.7.30版本,并且A中的代码引用了slf4j-api-1.7.30版本的新方法和类,如下图所示,这种情况下maven根据- 声明优先原则 : 同级依赖,先声明的覆盖后声明的(对于传递性依赖)会引入slf4j-api-1.7.26版本的依赖,那么问题就来了,当项目运行起来时,A依赖中的代码执行时就会报错了,因为它找不到某些方法和类,这就是典型的依赖冲突!
在这里插入图片描述
这种情况下我们可以通过排除掉easyExcel中的依赖来让maven选择使用A的子依赖,就像下面这样

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>2.1.6</version>
      <exclusions>
        <exclusion><!--手动排除-->
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

这样就可以正确的引入slf4j-api-1.7.30了!

tips

可能有的小伙伴会问,编译器在编译代码的时候不会检查我们引入的依赖的的代码中的方法和类是否存在的吗?
其实是不会的,因为那是已经编译好的class字节码文件,所以依赖冲突一般只在运行时产生。
GPT回答如下:(问题:Java编译代码的时候只会编译我们写的代码吗?)
是的,Java编译器在编译Java源代码时,只会编译我们自己编写的Java类。它并不会自动编译我们所依赖的的第三方库,因为这些库已经编译好了,生成了对应的.class字节码文件。
当我们在Java源代码中调用依赖库中的类或方法时,编译器会检查这些依赖库中所引用的类是否存在,如果存在,则会将它们的字节码文件打包到生成的class文件中,一并输出到编译后的目标代码中。
但如果我们修改了依赖库的源代码,那么需要重新对依赖库进行编译生成新的.class文件,然后再对主程序进行编译和运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/580318.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Collections提供的同步包装方法

Java同步容器类是通过synchronized&#xff08;内置锁&#xff09;来实现同步的容器&#xff0c;比如Vector、 HashTable以及SynchronizedList等容器。 线程安全的同步容器类主要有&#xff1a; Vector、 Stack、 HashTable等。 Collections提供的同步包装方法 Java提供一组包…

VTK Java项目构建和运行

date: 2019-04-02 10:24:00 VTK Java项目构建和运行 准备工作 本文的运行环境是Ubuntu。在自己建立的VTK build的文件夹&#xff08;这里名称为VTK-bin&#xff0c;见前文&#xff09;&#xff0c;找到vtk.jar&#xff0c;这里在VTK-bin/lib下。 新建工程 使用JetBrains的I…

【图】概念、存储结构、广度优先遍历遍历、深度优先遍历 - 详解

目录 前言 一、图 1.1、基本概念 二、图的存储结构 2.1、存储结构 2.1、邻接矩阵&#xff08;考察重点&#xff09; 2.1.1、代码实现 2.2、邻接表 2.3.1、无向邻接表存储 2.3.2、有向图邻接表存储 3.1、图的广度优先遍历&#xff08;层序遍历&#xff09; 3.2、图的…

Wails + Go 实现图形化桌面应用

效果展示 编写一个热点查看程序&#xff0c;包含百度热搜、微博热搜、头条、知乎等&#xff0c;废话不说上效果图&#xff1a; 效果图1&#xff1a; 效果图2 打包大小 涉及技术点 Golang 使用golang 1.9 编写代码 Wails vue3 使用Wails技术实现GUI渲染&#xff0c;页…

网络——网络协议总结

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。座右铭&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石&#xff0c;故能成其高。 个人主页&#xff1a;小李会科技的…

笔记本安装CentOS

目标: 1.利用闲置笔记本 2.省电/提高利用率/不安装图形桌面/最小化安装/附加选项:开发工具 step1&#xff1a;镜像下载 CentOS-7.9 163镜像 阿里云镜像 清华大学镜像 随便选一个 step2: 下载U盘系统盘制作工具Rufus U盘写入镜像/安装 step3: 安装完毕进入系统 …

2023年上半年软考学习总结(超详细)

目录 前言 一、背景1.1上次考试感受&#xff1a;1.2这次考试感受&#xff1a;1.3方法&#xff1a; 二、 过程2.1计算机网络概论计算机组成数据表示相关知识校验码相关知识计算机体系结构网络体系结构OSI/RM和TCP/IP计算机安全性可靠性性能评价 2.2 程序设计语言基础知识编译和解…

如何在华为OD机试中获得满分?Java实现【求最小公倍数】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

【Unity3D】广告牌特效

1 前言 广告牌特效是指&#xff1a;空间中的一个 2D 对象始终&#xff08;或尽可能&#xff09;面向相机&#xff0c;使得用户能够尽可能看清楚该 2D 物体。广告牌特效一共有以下 3 种&#xff1a; 正视广告牌&#xff1a;广告牌始终以正视图姿态面向相机&#xff0c;即广告牌…

异常检测进阶梳理1:Tabular AD视角

接触异常检测领域也有一年多的时间了&#xff0c;过程中遇到不少坑&#xff0c;知识体系也在不断更新完善&#xff0c;这里以专题的形式进行知识体系的梳理~ 异常检测&#xff08;Anomaly Detection, AD&#xff09;领域内的划分体系较多&#xff0c;这里基于异常检测最常用到的…

【P39】JMeter 随机顺序控制器(Random Order Controller)

文章目录 一、随机顺序控制器&#xff08;Random Order Controller&#xff09;参数说明二、测试计划设计2.1、测试计划一2.2、测试计划二 一、随机顺序控制器&#xff08;Random Order Controller&#xff09;参数说明 可以让控制器内部的组件按随机顺序执行&#xff08;内部…

Alibaba Arthas学习与使用

Alibaba Arthas学习与使用 目录 下载安装卸载退出快捷键重点部分: 命令 dashboardthreadjvmsyspropsysenvvmoptiongetstaticognlscsmjadmcredefinedumpclassloadermonitorwatchtracestackttoptionsprofiler 下载安装 # 下载 curl -O https://alibaba.github.io/arthas/art…

Apache Kafka - 如何实现可靠的数据传递

文章目录 可靠的数据传递导图 可靠的数据传递 Kafka 通过以下几个方面实现可靠的数据传递: 分区副本 - Kafka 的分区有多个副本,如果某个副本失效,其他副本可以继续服务。生产者重试 - 生产者在发送消息失败时会自动重试,一直到成功发送或者达到最大重试次数。批量确认 - 生产…

云服务器和专用服务器之间的区别

在当今数字化时代&#xff0c;服务器是构建和支持各种应用和服务的基础设施之一。随着技术的发展和需求的增加&#xff0c;出现了不同类型的服务器&#xff0c;其中最常见的是云服务器和专用服务器。本文将详细介绍云服务器和专用服务器之间的区别&#xff0c;以帮助您更好地了…

SpringSecurity从入门到实战

SpringSecurity从入门到实战 0. 简介 ​ Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 ​ 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有…

【LAMP架构】

目录 一、LAMP架构1、组件作用 二、编译安装Apache httpd服务2、安装环境依赖包3、配置软件模块4、编译及安装5、优化配置文件路径&#xff0c;并把httpd服务的可执行程序文件放入路径环境变量的目录中便于系统识别6.添加httpd系统服务7.修改httpd 服务配置文件8.浏览器访问验证…

【云原生|探索 Kubernetes 系列 5】简化 Kubernetes 的部署,深入解析其工作流程

前言 大家好&#xff0c;我是秋意零。 在前面 4 个章节中&#xff0c;我们充分了解了容器技术和 Kubernes 原生时代引擎的架构和设计思想&#xff0c;今天分享的主要内容是&#xff0c;探索 Kubernetes 部署&#xff0c;深入解析其工作流程 &#x1f47f; 简介 &#x1f3e0…

[元带你学: eMMC协议详解 11] Data transfer mode 数据传输模式

依JEDEC eMMC 5.1及经验辛苦整理&#xff0c;付费内容&#xff0c;禁止转载。 所在专栏 《元带你学: eMMC协议详解》 全文2300 字&#xff0c; 主要介绍数据传输模式&#xff0c;本节数据传输模式图非常重要。数据传输模式图可以说是我查对过最频繁的图之一了。eMMC 限定了这么…

数据库基础——6.排序与分页

这篇文章来讲一下数据库的排序与分页 目录 1.排序数据 1.1排序规则 1.2 单列排序 1.3 多列排序 2.分页 2.1 背景 2.2 实现规则 2.3 拓展 1.排序数据 1.1排序规则 使用 ORDER BY 子句排序 ASC&#xff08;ascend&#xff09;&#xff1a;升序 &#xff1b; DESC&a…

怎么一键保存浏览器中打开的所有标签页?

2023年5月28日&#xff0c;周日晚上&#xff1a; 被这个问题困扰很久了&#xff0c;之前一直不知道怎么全部保存浏览器中打开的所有标签页&#xff0c;浪费了不少的时间&#xff0c;今天下午偶然发现了解决办法。 很简单&#xff0c;直接在浏览器里使用快捷键“CtrlShiftD” …