Maven处理依赖冲突
- 什么是依赖冲突?
- 如何解决?
- Maven自动处理依赖冲突的规则
- 路径优先原则
- 第一声明优先原则
- 注意
- 子模块覆盖父模块
- 父模块声明dependency子模块覆盖dependency
- 父模块声明dependencyManagement 子模块覆盖dependency
- 父模块声明dependencyManagement 子模块覆盖dependencyManagement
- Maven手动处理依赖冲突
- Maven自动处理依赖后导致引入了低版本的依赖
- 解决方案
- exclusions
- optional
- 注意
- 工具
什么是依赖冲突?
当项目中直接或者间接的引入多个版本的同一依赖时则会出现依赖冲突
如何解决?
Maven自动处理依赖冲突的规则
路径优先原则
当依赖冲突发生时,
Maven会优先选择路径最短的依赖版本。路径长度是指从当前项目到依赖的层级深度。例如:项目直接引入的a:v1,及b:v1,但b:v1中引入了a:v2。那么项目自动会引入a:v1。因为a:v1比b:v1->a:v2路径更短
实例:
package-b引入了logback.1.5.14,及package-a但是,package->a引入了logback.1.5.13。直接maven选择了logback.1.5.14符合路径优先原则

第一声明优先原则
如果两个依赖的路径长度相同,
Maven会优先选择在pom.xml文件中先声明的依赖版本。例如:项目直接引入了a:v1->b:v1,与a:v2->b:v2但是a:v1是在a:v2前先声明的,那么就会选择a:v2中的b:v1反之选择b:v2

注意
坑!!!!
直接在pom.xml中引入两个相同坐标但不同版本的依赖时,不会按照声明优先原则选择。而是使用最后声明的依赖。


[WARNING] 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique: ch.qos.logback:logback-core:jar -> version 1.5.14 vs 1.5.13 @ line 23, column 21->表示同一个pom下不能声明相同的坐标。这就导致maven直接选择了最后声明的依赖
子模块覆盖父模块
子模块可以通过在自己的
pom.xml文件中直接声明依赖的版本来覆盖父模块的版本。Maven 的依赖解析规则会优先考虑子模块中直接声明的依赖版本。
父模块声明dependency子模块覆盖dependency

父模块声明dependencyManagement 子模块覆盖dependency

父模块声明dependencyManagement 子模块覆盖dependencyManagement

Maven手动处理依赖冲突
Maven自动处理依赖后导致引入了低版本的依赖
package-g:1.0,package-g:2.0。通常我们是使用高版本的包,但是因为路径优先原则,导致使用了低版本的依赖。这种就需要手动解决了。

解决方案
思路:通常我们高版本的依赖兼容低版本的依赖。那么我只需要依赖高版本的依赖即可。
exclusions
使用于不能修改package-h内部的场景
<dependencies>
<dependency>
<groupId>com.mfyuan</groupId>
<artifactId>package-j</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.mfyuan</groupId>
<artifactId>package-h</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.mfyuan</groupId>
<artifactId>package-g</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
将低版本的依赖通过
exclusion给排除掉即可。这样就没有发生依赖冲突了。

optional
optional为true时,不将该依赖传递给外层。这样就可以避免造成依赖冲突的问题。
适用场景:可以修改package-h内部的pom.xml一般都为自己开发的jar包
<dependencies>
<dependency>
<groupId>com.mfyuan</groupId>
<artifactId>pacage-g</artifactId>
<version>1.0-SNAPSHOT</version>
<!--不将该依赖传递给外层-->
<optional>true</optional>
</dependency>
</dependencies>

注意
高版本如果没有兼容低版本怎么办?这种情况会造成
编译失败,或者ClassNotFoundException。如果你又需要高版本的功能也需要低版本的功能那么这种问题是解决不了的。
工具
idea插件:Maven Helper

可以快速查看那些依赖存在冲突



















