maven依赖的冲突如何解决?

2020-05-04 11:03:26 java常见问答 7094

大家是否了解maven呢?为什么会产生依赖冲突呢?有什么解决的方案呢?接下来一起来了解下吧。

首先我们来看一下依赖冲突产生的原因:

1. 如果项目的依赖A和依赖B同时引入了依赖C。

2. 如果依赖C在A和B中的版本不一致就可能依赖冲突。

3. 比如 项目 <- A, B, A <- C(1.0),B <- C(1.1)。

4. 那么maven如果选择高版本C(1.1)来导入(这个选择maven会根据不等路径短路径原则和同等路径第一声明原则选取),C(1.0)中的类c在C(1.1)中被修改而不存在了。

5. 在编译期可能并不会报错,因为编译的目的只是把业务源代码编译成class文件,所以如果项目源代码中没有引入共有依赖C因升级而缺失的类c,就不会出现编译失败。除非源代码就引入了共有依赖C因升级而缺失的类c则会直接编译失败。

6. 在运行期,很有可能出现依赖A在执行过程中调用C(1.0)以前有但是升级到C(1.1)就缺失的类c,导致运行期失败,出现很典型的依赖冲突时的NoClassDefFoundError错误。

7. 如果是升级后出现原有的方法被修改而不存在的情况时,就会抛出NoSuchMethodError错误。

那么怎么来解决依赖冲突呢?

1. 首先可以借助Maven查看依赖的依赖树来分析一下:mvn dependency:tree,或者使用IDEA的插件Dependency Analyzer插件来可视化地分析依赖关系。这个过程后可以明确哪些dependency引入了可能会冲突的依赖。

2. 比如我们的项目引入A的依赖C为1.1版本,引入的B会在内部依赖C的1.0版本,那么Dependency Analyzer插件会出现依赖冲突提示,会提示B引入的C的1.0版本和当前选用的C的1.1版本冲突因而被忽略(1.0 omitted for conflict with 1.1)。

3. 如果这时候打war包出来启动很有可能会遇到因依赖冲突而出现的NoClassDefFoundError或NoSuchMethodError,导致编译期正常的代码无法在运行期跑起来。

4. 由于A引入的C的版本高而B依赖的C版本低,我们优先会选择兼容高版本C的方案,即试图把B的版本调高以使得引入的依赖C可以和A引入的依赖A达到一致的版本,以此来解决依赖冲突。当然这是一个理想状况。

5. 如果找到了目前已有的所有的B的版本,均发现其依赖的C没有与A一致的1.1版本,比如B是一个许久未升级的旧项目,那么也可以考虑把A的版本拉低以使得C的版本降到与B一致的1.0版本,当然这也可能会反过来导致A不能正常工作。

6. 上面已经可以看出来解决依赖冲突这件事情并不简单,很难顾及两边,很多情况下引入不同版本依赖的很可能超过两方而是更多方。

7. 那么来考虑一下妥协的方案,如果A引入的C使用的功能并不跟被抛弃的类或方法有关,而是其他在1.1版本中仍然没有改变的类或方法,那么可以考虑直接使用旧的1.0版本,那么可以使用exclusion标签来在A中排除掉对C的依赖,那么A在使用到C的功能时会使用B引入的1.0旧版本C。即A其实向B妥协使用了B依赖的C。

以上就是今天所讲的maven依赖的知识,如果想要了解更多关于java常见问答的知识,请继续关注本网站。