Maven 依赖排查

devtools/2024/9/24 5:30:06/

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

我们想看一下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的依赖树可能看起来像这样

java">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。

java">ProjectA
|-- LibraryB|-- LibraryX1.0
|-- LibraryC|-- LibraryX2.0

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

java"><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部分统一指定一个兼容的版本(把问题提给项目的维护者吧)。

java"><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博客


http://www.ppmy.cn/devtools/42180.html

相关文章

Kibana使用

一、什么是Kibana   Kibana 是一个开源的分析和可视化平台&#xff0c;Kibana 提供搜索、查看和与存储在 Elasticsearch 索引中的数据进行交互的功能。开发者或运维人员可以轻松地执行高级数据分析&#xff0c;并在各种图表、表格和地图中可视化数据。 Kibana使用&#xff1a…

【Maven】Nexus私服简介_下载安装_登录

1、简介 1.1介绍 Nexus私服&#xff0c;也被称为Maven仓库管理器&#xff0c;是许多公司在自己的局域网内搭建的远程仓库服务器。提供了强大的仓库管理功能和构件搜索功能&#xff0c;使得开发人员能够更方便地管理和使用Maven项目中的依赖库。 1.2作用 内网访问&#xff1…

网络安全快速入门(十三)linux及vmware软件的网络配置

13.1 前言 在通过我们前面的了解&#xff0c;我们现在已经对Linux的基础知识有了大致的了解&#xff0c;今天我们来大概讲一下关于linux系统及vmware的网络配置问题&#xff0c;在这之前&#xff0c;我们需要对网络有一个大概的认识和了解&#xff0c;话不多说&#xff0c;我们…

【JS】基于原生JavaScript的大文件切片上传及断点续传实现

基于原生JavaScript的大文件切片上传及断点续传实现 在现代Web应用中,大文件上传是一个常见但具有挑战性的功能。随着文件大小的增加,如何高效可靠地上传文件至服务器成为亟待解决的问题。在本文中,我将介绍如何使用原生JavaScript实现大文件切片上传及断点续传功能。 为什…

Python数据分析与数据可视化 概念

考试题型&#xff1a; 一、填空题&#xff08;1分*10&#xff09; 二、程序代码填空&#xff08;1分*20&#xff09; 三、读程序写结果&#xff08;10分*4&#xff09; 四、程序设计&#xff08;10分*1&#xff09; 五、问答题&#xff08;20分*1&#xff09; 考试范围&#x…

JavaScript-基本数据类型和变量

基本数据类型 JavaScript支持数字、字符串和布尔值3种基本数据类型 字符串型 字符串型是JavaScript用来表示文本的数据类型&#xff0c;字符串通常由单引号或双引号括起来&#xff0c;如果字符串存在特殊字符&#xff0c;可以用转义字符代替 数字型 数字型也是JavaScript中的基…

听力 5.16

directing&#xff1a;指示 defend&#xff1a;保护 on the heels of :在xx之后 intellectual property theft :窃取知识产权 force tech transfer&#xff1a;强迫技术转让 artificially&#xff1a;人为 corner the market&#xff1a;垄断市场 tremendous vulnerabi…

解决 Content type ‘application/json;charset=UTF-8‘ not supported

文章目录 问题描述原因分析解决方案参考资料 问题描述 我项目前端采用vue-elementUi-admin框架进行开发&#xff0c;后端使用SpringBoot&#xff0c;但在前后端登录接口交互时&#xff0c;前端报了如下错误 完整报错信息如下 前端登录接口JS代码如下 export function login(…