java maven依赖传递以及版本冲突

基本背景

你使用 java,使用 maven pom.xml 管理你的依赖包
可能常常遇到依赖版本冲突,或者很多依赖包,不清楚到底使用哪个依赖的版本

基本排查冲突工具

idea 可以下载 mavenHelper 插件,可以很方便来做依赖冲突的排查

原始的可以使用 mvn 命令

mvn dependency:tree -Dverbose

依赖传递:很多依赖到底使用哪个版本的依赖

比如 A 项目中使用 B 依赖,B 项目中使用了 C 依赖,
再同时 A 项目中使用了 D 依赖,D 项目中使用了 C 依赖,
再同时 A 项目中使用了 E 依赖,E 项目中使用了 F 依赖,F 项目中使用了 C 依赖
再同时 A 项目中使用了 C 依赖

即:

  • A -> B -> C(1.0)
  • A -> D -> C(2.0)
  • A -> E -> F -> C(3.0)
  • A -> C(4.0)

那么 A 项目 run 起来后代码逻辑到底使用哪个版本的 C 依赖在跑呢?

首先得明确,并不是 A 自己的代码逻辑使用 4.0 的 C,然后 A 项目中运行到 B 中的代码时候就按照 1.0 的 C 去跑,并不是这样的,统一在 runing 的 A 项目统一使用一个版本的 C 的依赖在 run

依赖传递规则:

  • 路径浅的优先级高
  • 同层路径的谁先声明谁优先级高

所以按照这样的规则我们知道:
C(4.0) > C(1.0) > C(2.0) > C(3.0)

所以 A 项目将使用 4.0 的 C 在 run

dependencyManagement 作用

同样的例子:

  • A -> B -> C(1.0)
  • A -> D -> C(2.0)
  • A -> E -> F -> C(3.0)
  • A -> C(4.0)

如果你设立了 dependencyManagement 中,指定了 C 的版本是 5.0,当 A 不存在直接声明的依赖 C(4.0) 时,它将统一按照 C(5.0) 的版本去 run,如果 A 直接声明了 C 的版本,则优先级最高的是 A 直接声明的 C 的版本

所以优先级上:
A 直接声明的版本 > dependencyManagement 指定的版本 > 路径更浅的依赖版本 > 同深浅则是率先声明的依赖版本

exclusions

依赖中 exclusions 掉某个子依赖,目的是防止内部依赖往外部传递,比如 A -> B,B 项目中有 C 依赖,如果 A 没有直接的 C 依赖,那么 A 使用的是 B 中的 C 依赖的版本,当 B exclusion 掉了 C,则表示这个 C 依赖无法传递到 A

一些场景

如果A项目只我需要引入C依赖包,然后B项目也需要引入C依赖包,可是自己的C依赖包会需要依赖D依赖包的3.0版本,而我的A项目中又直接声明需要依赖D依赖的1.0版本,B项目中又直接声明了需要依赖D项目的2.0版本,这种情况该怎么办?

解决:
方法一(推荐):如果 A 和 B 项目升级 D 的版本不影响,那么A 和 B 项目统一升级下 D 的版本为 3.0
方法二:考虑降低 C 的版本,或者 C 项目如果是你自己的可以考虑降低 C 中 D 的版本
方法三(复杂):

  • OSGi:通过类加载器隔离不同版本的D
  • Java 9+模块化:使用module-info.java限定模块可见性
  • 自定义ClassLoader:手动控制类加载路径(风险较高)

其他问题

依赖隔离?
如果 A -> B -> C,同时也有 A -> C,我想让 A 在 run 时候,A 使用自己的 C 依赖版本,run 到代码 B 到地方使用 B 内部依赖 C 的版本,这样一般是不可行的,如果非要做则使用 Maven Shade 插件来重定位依赖。这样其实做起来比较麻烦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

abcnull

您的打赏是我创作的动力之一

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值