Maven 依赖排查

先从项目去看显而易见,假如我们有一个项目,父工程中包含一些子工程,如下:

我们想看一下samples-account中的依赖关系,那么我们可以打开 samples-account的pom文件,查看其maven依赖关系图。

我们可以看到此项目中maven的依赖关系如下。

 我们可以看到有很多红色的虚线和红色的实线,对于红色实线来说表示的是maven依赖冲突,对于红色虚线来说表示的是重复依赖或者是依赖被覆盖。

因为很乱,我们可以先按如下操作找到哪些有问题的依赖关系。

然后再找到我们要关注的依赖进行分析,如我们要看spring-context-support相关的依赖是否有冲突。我们可以左键单击选中这个节点,然后点击如下按钮:

 会自动关注到此依赖,如下图:

这样我们可以看到 spring-context-support 有俩版本,且samples-account直接引用过其1.0.5版本,dubbo-config-spring也引用过其1.0.5,dubbo则引用的是他的1.0.11版本(在这里由于就近原则,它的版本被改为1.0.5版本了)。我们从maven树中也能看到:

 那么jar包后面的omitted for conflict with 1.0.5是什么意思呢?

在 Maven 的依赖树中,当你看到“omitted for conflict with 1.0.5”这样的信息时,它意味着 Maven 在解析依赖时遇到了版本冲突,并决定省略(排除)了与指定版本(在此例中为 1.0.5)冲突的那个依赖。

具体来说,Maven 遵循了一套复杂的依赖解析算法,称为“最近者胜”(nearest wins)策略。当 Maven 检测到多个库都依赖了同一个库的不同版本时,它会根据依赖树中的层次结构和声明的顺序来决定使用哪个版本。在这个过程中,如果一个依赖被其他依赖以更高的版本或相同的版本引入,那么 Maven 可能会选择忽略(省略)那个较低版本的依赖。

例如,假设你有以下依赖结构:

  • 项目 A 依赖库 B 1.0.0
  • 库 B 1.0.0 依赖库 C 1.0.0
  • 项目 A 同时直接依赖库 C 1.0.5

在这种情况下,Maven 会选择库 C 的 1.0.5 版本,因为这是一个更直接的依赖,并且版本号更高。同时,它会将库 B 1.0.0 依赖的库 C 1.0.0 标记为“omitted for conflict with 1.0.5”,意味着它已经被省略了,以避免版本冲突。

如果你希望明确控制依赖的版本,你可以在项目的 pom.xml 文件中使用 <dependencyManagement> 部分来管理依赖的版本,或者使用 <exclusions> 标签来排除不需要的传递性依赖。

而omitted for duplicate又是什么意思呢?

 在Maven中,"omitted for duplicate"意味着存在多个具有相同groupIdartifactId的依赖项,但它们的版本不同或传递依赖路径不同,因此Maven或相关的构建工具(如IntelliJ IDEA)认为这些依赖是重复的。

具体来说,当Maven解析项目的依赖关系时,如果它发现两个或多个依赖项指向了同一个库(即相同的groupIdartifactId),但它们的版本不同,Maven就会尝试解决这种冲突。Maven的依赖调解机制会选择一个版本作为“赢家”,并将其他版本标记为“输家”。被标记为“输家”的依赖项在依赖树中可能就会被标记为"omitted for duplicate",表示它们因为与另一个相同但版本不同的依赖项冲突而被省略。

这种情况通常发生在项目的依赖关系比较复杂,特别是当项目直接或间接地通过传递依赖引入了同一个库的不同版本时。为了避免这种问题,可以在项目的pom.xml文件中使用<dependencyManagement>部分来管理依赖的版本,或者使用<exclusions>标签来排除不需要的传递性依赖。

 omitted for conflict with 和 omitted for duplicate有什么区别呢?

在Maven依赖管理的上下文中,omitted for conflict with 和 omitted for duplicate 这两个术语都与解决依赖冲突有关,但它们在描述冲突的原因和结果时略有不同。

  1. omitted for duplicate

    • 这通常表示在项目的依赖树中存在多个具有相同groupIdartifactId但可能不同版本的依赖项。Maven的依赖管理策略在处理这些依赖时,会选择一个版本(通常是最新版本,但也取决于依赖的声明顺序和范围),而将其他版本视为“重复的”并省略它们。
    • 当你在Maven的输出或日志中看到“omitted for duplicate”时,这通常意味着Maven已经自动解决了这个冲突,并选择了其中一个依赖项版本。
  2. omitted for conflict with

    • 这个术语更具体地指出了哪个依赖项与当前考虑的依赖项存在冲突。它表明,尽管两个依赖项在groupIdartifactId上匹配,但由于某种原因(例如,它们的版本不兼容或与其他依赖项存在冲突),Maven选择了省略其中一个。
    • “conflict with”后面通常会跟着与当前依赖项存在冲突的依赖项的详细信息,如版本号或groupId:artifactId组合。
    • 与“omitted for duplicate”不同,“omitted for conflict with”可能意味着需要手动干预来解决冲突,特别是当Maven的自动依赖管理策略不能提供一个满意的解决方案时。

总之,这两个术语都涉及Maven在构建项目时如何处理依赖冲突,但“omitted for duplicate”更侧重于描述多个相同依赖项的存在,而“omitted for conflict with”则更具体地指出了哪个依赖项与当前依赖项存在冲突。

对于这些冲突我们怎么解决呢?

假设你的项目(我们称之为project-A)依赖于两个库:library-Xlibrary-Y

  1. library-X 的版本1.0是你的项目直接依赖的。
  2. library-Y 是你的项目直接依赖的另一个库,但它又间接地依赖于library-X的版本2.0(作为它的传递性依赖)。

在Maven的依赖管理中,这会导致一个冲突,因为你的项目试图同时使用library-X的两个不同版本:1.0(直接依赖)和2.0(通过library-Y的传递性依赖)。

Maven的依赖树可能看起来像这样

project-A  
|-- library-X:1.0 (直接依赖)  
|-- library-Y:some-version  
    |-- library-X:2.0 (传递性依赖)

在这个例子中,Maven会尝试解决这个冲突。默认情况下,Maven会选择路径最短的依赖版本,也就是说,它会尽可能地使用直接声明的依赖版本。但是,这并不总是可行的,特别是当两个版本在API或行为上有不兼容的更改的时候。

当然还有项目依赖是这样冲突的:

1.projectA依赖LibraryB,LibraryB又依赖LibraryX1.0。

2.projectA依赖LibraryC,LibraryC又依赖LibraryX2.0。

ProjectA
|-- LibraryB
	|-- LibraryX1.0
|-- LibraryC
	|-- LibraryX2.0

要解决上述Maven依赖冲突问题,你可以通过在项目的pom.xml文件中配置<exclusions>标签来排除不需要的依赖版本。以下是一个示例配置,展示了如何排除LibraryB中的LibraryX 1.0版本依赖,以确保ProjectA只使用LibraryX的2.0版本(假设这是你想要保留的版本):

<project>  
    ...  
    <dependencies>  
        <!-- ProjectA依赖于LibraryB -->  
        <dependency>  
            <groupId>com.example</groupId>  
            <artifactId>LibraryB</artifactId>  
            <version>1.0</version>  
            <exclusions>  
                <!-- 排除LibraryB中的LibraryX 1.0版本 -->  
                <exclusion>  
                    <groupId>com.some.othergroup</groupId>  
                    <artifactId>LibraryX</artifactId>  
                </exclusion>  
            </exclusions>  
        </dependency>  
  
        <!-- ProjectA也依赖于LibraryC -->  
        <dependency>  
            <groupId>com.example</groupId>  
            <artifactId>LibraryC</artifactId>  
            <version>x.y.z</version>  
            <!-- 注意:这里不需要排除LibraryX,因为我们要保留的版本就是LibraryC所依赖的版本 -->  
        </dependency>  
  
        <!-- 直接指定LibraryX的2.0版本 -->  
        <dependency>  
            <groupId>com.some.othergroup</groupId>  
            <artifactId>LibraryX</artifactId>  
            <version>2.0</version>  
        </dependency>  
  
        <!-- 其他依赖... -->  
    </dependencies>  
    ...  
</project>

看着好像有那么点道理,然而,在上面的配置中,直接指定LibraryX的2.0版本可能会引发另一个问题:如果LibraryB确实需要LibraryX的1.0版本来正常工作,那么这种硬编码的依赖可能会导致LibraryB无法正常工作。

因此,更好的做法可能是确保LibraryBLibraryC维护者都更新他们的依赖项以使用兼容的版本,或者在项目的dependencyManagement部分统一指定一个兼容的版本(把问题提给项目的维护者吧)。

<project>  
    ...  
    <dependencyManagement>  
        <dependencies>  
            <!-- 统一指定LibraryX的版本为2.0 -->  
            <dependency>  
                <groupId>com.some.othergroup</groupId>  
                <artifactId>LibraryX</artifactId>  
                <version>2.0</version>  
            </dependency>  
            <!-- 其他依赖管理... -->  
        </dependencies>  
    </dependencyManagement>  
  
    <dependencies>  
        <!-- ProjectA依赖于LibraryB,但不需要显式排除LibraryX,因为dependencyManagement已经指定了版本 -->  
        <dependency>  
            <groupId>com.example</groupId>  
            <artifactId>LibraryB</artifactId>  
            <version>1.0</version>  
        </dependency>  
  
        <!-- ProjectA也依赖于LibraryC,同样不需要显式排除 -->  
        <dependency>  
            <groupId>com.example</groupId>  
            <artifactId>LibraryC</artifactId>  
            <version>x.y.z</version>  
        </dependency>  
  
        <!-- 通常情况下,不需要直接指定LibraryX的版本,因为dependencyManagement已经处理了 -->  
  
        <!-- 其他依赖... -->  
    </dependencies>  
    ...  
</project>

 在dependencyManagement部分指定的版本将作为项目的“首选”版本,Maven将尝试解析所有依赖以使用这个版本(除非在dependencies部分明确指定了不同的版本)。

具体依赖可参照这位博主的描述:maven依赖传递(直接、间接依赖)、解决依赖冲突(排除依赖、版本锁定dependencyManagement)_maven 间接依赖-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WPS如何把多个表格合并到一个表格里面?

注意&#xff1a;此功能需要wps会员。 例如&#xff1a;这里有3个表格。 现在希望合并3个表格到一起&#xff0c;如下图所示。 新建一个表格&#xff0c;打开表格。 选择 开始->工作表->合并表格->整合成为一个工作薄。 弹出对话框&#xff0c;选择添加文件&#xff…

JETBRAINS IDES 分享一个2099通用试用码,支持一键升级!DataGrip 2024 版

文章目录 废话不多说上教程&#xff1a;&#xff08;动画教程 图文教程&#xff09;一、动画教程激活 与 升级&#xff08;至最新版本&#xff09; 二、图文教程 &#xff08;推荐&#xff09;Stage 1.下载安装 toolbox-app&#xff08;全家桶管理工具&#xff09;Stage 2 : 下…

AndroidStudio集成高德地图后出现黑屏并报错

报错内容为&#xff1a;No implementation found for void com.autonavi.base.ae.gmap.GLMapEngine.nativeMainThreadTrigger(int, long) (tried Java_com_autonavi_base_ae_gmap_GLMapEngine_nativeMainThreadTrigger and Java_com_autonavi_base_ae_gmap_GLMapEngine_nativeM…

最佳解决Maven同一依赖多版本共存问题,重复依赖(同一个jar包,多个版本)-maven-shade-plugin

先看链接:原文链接 参照原文链接生成的文件(下面是我放的位置) mvn指令 mvn install:install-file -DfileD:\mavenrepository/maven-shade.jar -DgroupIdcom.wj -DartifactIdmaven-shade -Dversion1.1 -Dpackagingjar如果配置了maven_home 和java_home可以任意打开cmd执行(…

Linux-软件安装--tomcat的安装

tomcat的安装 1、下载tomcat安装包2.移动到自己想要解压的目录3、解压文件夹4、启动tomcat5、查看tomcat进程6、查看日志7、通过浏览器访问成功8、停止tomecat服务8.1运行tomcat的bin目录中提供的停止服务的脚本文件shutdcwn.sh8.2结束tomcat进程1、下载tomcat安装包 本篇文章…

Vue原理学习:vdom 和 diff算法(基于snabbdom)

vdom 和 diff 背景 基于组件化&#xff0c;数据驱动视图。只需关心数据&#xff0c;无需关系 DOM &#xff0c;好事儿。 但是&#xff0c;JS 运行非常快&#xff0c;DOM 操作却非常慢&#xff0c;如何让“数据驱动视图”能快速响应&#xff1f; 引入 vdom 用 vnode 表示真实…

邮件API接口的优势有哪些?如何有效整合?

邮件API怎么选&#xff1f;SendCloud与AokSend的性能对比分析&#xff1f; 邮件API接口作为企业与用户沟通的重要桥梁&#xff0c;其重要性不言而喻。Aok将深入探讨邮件API接口的优势、有效整合的方法、选择标准以及SendCloud与AokSend两款邮件发送服务的性能对比分析。 邮件…

这10款安卓APP,简直好用到爆!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频http://AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频 1.追书——追书神器 追书神器是小说追新大神&#xff0c;全网实…

【大模型微调】一文掌握7种大模型微调的方法

本篇文章深入分析了大型模型微调的基本理念和多样化技术&#xff0c;细致介绍了LoRA、适配器调整(Adapter Tuning)、前缀调整(Prefix Tuning)等多个微调方法。详细讨论了每一种策略的基本原则、主要优点以及适宜应用场景&#xff0c;使得读者可以依据特定的应用要求和计算资源限…

Jquery+Servlet+JDBC实现登录注册功能

前端部分 HTMLCSS部分 引入JQuery包和JQuery.cookie包&#xff0c;前者封装了DOM操作的一些方法&#xff0c;后者封装了对cookie的操作 我们使用cookie主要是为了做登录后页面的跳转时&#xff0c;能存下来这个用户是谁&#xff0c;这样后面可以对单一用户进行操作&#xff…

使用API有效率地管理Dynadot域名,默认将域名隐形转发至其他界面

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

webpack优化构建速度示例-resolve.extensions:

当项目不仅仅包含.js或.json文件&#xff0c;还包含其他类型文件(如.ts、.vue、.css)作为模块时&#xff0c;配置resolve.extensions可以不必要的文件搜索提高性能。 src/index.ts import { someFuction } from ./modulesomeFuction()src/module.tsimport {otherSomeFuction} f…

三分钟快速上手SpringSecurity框架

导入依赖框架 web 框架(spring-boot-starter-web) <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> springSecurity 框架(spring-boot-starter-security) <de…

【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置

本节博客主要是通过“在排序数组中查找元素的第一个和最后一个位置”总结关于二分算法的左右界代码模板&#xff0c;有需要借鉴即可。 目录 1.题目2.二分边界算法2.1查找区间左端点2.1.1循环条件2.1.2求中点的操作2.1.3总结 2.2查找区间右端点2.1.1循环条件2.1.2求中点的操作2.…

vue框架学习--表单校验

在使用 Element UI&#xff08;一个常见的 Vue UI 组件库&#xff09;&#xff0c;要给 添加表单验证&#xff0c;Element UI 的表单验证通常通过 Form 和 FormItem 组件以及它们的 rules 属性来实现。下面是一个例子&#xff0c;展示如何给联系人字段添加表单验证&#xff1a;…

网页打开:为什么国内用新标签页,国外用当前页?

想写这个话题很久了&#xff0c;因为用百度和Google搜索时&#xff0c;打开搜索结果链接时的交互差异&#xff0c;几乎每天都要提醍我一下。 网页打开——这个交互&#xff0c;在设计里&#xff0c;算是极微小&#xff0c;但影响极广泛的操作设计。甚至&#xff0c;因此形成了…

使用Python处理Excel数据:去除列中的双引号

目录 引言 技术背景 步骤概述 代码示例 案例分析 扩展内容 1. 处理多个列中的双引号 2. 处理大型Excel文件 3. 自定义函数处理数据 4. 错误处理和日志记录 结论 引言 在当今信息爆炸的时代&#xff0c;数据已经成为了各个行业最宝贵的资源之一。而Excel&#xff0c…

转载 | 大佬3万字深度分析:2024全球游戏业正在遭遇什么困境?

2022年&#xff0c;游戏业当时的裁员人数达到了破纪录的8500人&#xff0c;2023年这个数字几乎增长了20%&#xff0c;然后在2024开年的两个月&#xff0c;就已经有7800人丢掉了工作。伴随着这些裁员的&#xff0c;是大量表现不及预期的或者完全失败的游戏&#xff0c;还有更多处…

人工智能(一)架构

一、引言 人工智能这个词不是很新鲜&#xff0c;早就有开始研究的&#xff0c;各种推荐系统、智能客服都是有一定的智能服务的&#xff0c;但是一直都没有体现出多高的智能性&#xff0c;很多时候更像是‘人工智障’。 但是自从chatGpt3被大范围的营销和使用之后&#xff0c;人…

Hbuild-X运行ios基座app

一、说明 ios真机第一次运行的时候需要下载插件&#xff0c;这个都是自动监测&#xff0c;自动下载的&#xff0c;不用多说。ios真机运行是需要签名的&#xff0c;不然就会报以下错误。如何制作免费的签名证书呢&#xff0c;需要借助爱思助手来完成。 二、安装爱思助手 &…