依赖冲突
冲突产生原因:
条件:
一个项目在引入依赖包时,要引入A依赖包和B依赖包,而A、B依赖包需要同时引入不同版本的C依赖包
项目 <- A, B
A <- C(1.0)
B <- C(1.2)。
在IDEA使用Maven来进行依赖管理时,Maven选择高版本C(1.2)来导入(Maven是根据不等路径短路径优先原则和同等路径第一声明原则来选择版本包),此时C(1.0)中的类c1在C(1.1)中被修改而不存在了。
结果:
- 编译期:在进行以把业务源代码编译成Class文件为目的的编译时,源代码中在没有引入共有依赖C因升级而缺失的类c1,可能不会提示出错。【源代码就引入了共有依赖C因升级而缺失的类c1则会直接编译失败。】
- 运行期: 当依赖A在执行过程中调用C(1.2)缺失的类c1时,会导致运行失败,出现典型的依赖冲突。NoClassDefFoundError
- 升级:对源码进行升级后出现原有的方法被修改但不存在的情况时(原先引入的时C(1.0),升级后引入C(1.2)),会报错误。NoSuchMethodError
解决方案
- 使用Maven检查依赖树:mvn dependency:tree,或者使用IDEA的插件Dependency Analyzer插件进行可视化分析依赖关系。可以明确哪些pom.xml文件中dependency引入了可能会冲突的依赖。
- 由于B依赖需要的C依赖(1.2)的版本高而A依赖的C依赖(1.0)版本低,优先选择兼容高版本C(1.2)的方案,即试图把A需要的C依赖版本调高以使得引入的C依赖可以和B引入的依赖C达到一致的版本,以此来解决依赖冲突。
- 目前已有的所有A版本,均发现其依赖的C没有与B一致的1.2版本时,可以考虑把B的版本拉低以使得C的版本降到与A一致的1.0版本,当然这也可能会反过来导致B不能正常工作。
- 如果A引入的C依赖使用的功能并不和被抛弃的类C1或方法有关,而是其他在1.2版本中仍然存在且没有改变的类或方法,可以直接使用1.2版本,并且使用exclusion标签来在A中排除掉对C(1.2)的依赖,那么A在使用到C的功能时会使用B引入的1.2版本C。即A其实向B妥协使用了B依赖的C(1.2)。