摘要:首先我们来看一下依赖冲突产生的原因如果项目的依赖和依赖同时引入了依赖。除非源代码就引入了共有依赖因升级而缺失的类则会直接编译失败。
maven定义了许多dependency,每个dependency内部也会定义它的dependency。
首先我们来看一下依赖冲突产生的原因:如果项目的依赖A和依赖B同时引入了依赖C。
如果依赖C在A和B中的版本不一致就可能依赖冲突。
比如 项目 <- A, B, A <- C(1.0),B <- C(1.1)。
那么maven如果选择高版本C(1.1)来导入(这个选择maven会根据不等路径短路径原则和同等路径第一声明原则选取),C(1.0)中的类c在C(1.1)中被修改而不存在了。
在编译期可能并不会报错,因为编译的目的只是把业务源代码编译成class文件,所以如果项目源代码中没有引入共有依赖C因升级而缺失的类c,就不会出现编译失败。除非源代码就引入了共有依赖C因升级而缺失的类c则会直接编译失败。
在运行期,很有可能出现依赖A在执行过程中调用C(1.0)以前有但是升级到C(1.1)就缺失的类c,导致运行期失败,出现很典型的依赖冲突时的NoClassDefFoundError错误。
如果是升级后出现原有的方法被修改而不存在的情况时,就会抛出NoSuchMethodError错误。
那么怎么来解决依赖冲突呢?首先可以借助Maven查看依赖的依赖树来分析一下:mvn dependency:tree,或者使用IDEA的插件Dependency Analyzer插件来可视化地分析依赖关系。这个过程后可以明确哪些dependency引入了可能会冲突的依赖。
比如我们的项目引入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)。
如果这时候打war包出来启动很有可能会遇到因依赖冲突而出现的NoClassDefFoundError或NoSuchMethodError,导致编译期正常的代码无法在运行期跑起来。
由于A引入的C的版本高而B依赖的C版本低,我们优先会选择兼容高版本C的方案,即试图把B的版本调高以使得引入的依赖C可以和A引入的依赖A达到一致的版本,以此来解决依赖冲突。当然这是一个理想状况。
如果找到了目前已有的所有的B的版本,均发现其依赖的C没有与A一致的1.1版本,比如B是一个许久未升级的旧项目,那么也可以考虑把A的版本拉低以使得C的版本降到与B一致的1.0版本,当然这也可能会反过来导致A不能正常工作。
上面已经可以看出来解决依赖冲突这件事情并不简单,很难顾及两边,很多情况下引入不同版本依赖的很可能超过两方而是更多方。
那么来考虑一下妥协的方案,如果A引入的C使用的功能并不跟被抛弃的类或方法有关,而是其他在1.1版本中仍然没有改变的类或方法,那么可以考虑直接使用旧的1.0版本,那么可以使用exclusion标签来在A中排除掉对C的依赖,那么A在使用到C的功能时会使用B引入的1.0旧版本C。即A其实向B妥协使用了B依赖的C。
来看个实例:
项目引入了4.2.5.RELEASE的spring-webmvc,同时引入了3.2.1.RELEASE的spring-security-web。
用Dependency Analyzer插件分析得到的依赖关系是这样的:
为什么maven会选择4.2.5.RELEASE引入呢,其实前文提到过:比如对spring-beans这个依赖来说spring-webmvc:4.2.5.RELEASE-spring-beans:4.2.5.RELEASE的路径是2,而spring-security-web:3.2.1.RELEASE-spring-security-core:3.2.1.RELEASE-spring-beans:3.2.8.RELEASE的路径是3,因此根据不等路径取短路径原则则选取了前者,即spring-beans:4.2.5.RELEASE,注意的是引入时并不是优先引入高版本的,同时如果依赖的路径长相等则取第一个出现的版本。
可以看到spring-security-web引入的一众spring依赖是3.X版本的,同spring-webmvc的4.2.5.RELEASE版本不一致。
果不其然,打好的war包启动的时候即会报错终止。
那么在我们的问题在于兼容高版本的spring-webmvc的4.2.5.RELEASE的情形下寻找spring依赖版本一致的spring-security-web,在www.mvnrepository.com寻找合适版本依赖的spring-security-web,最终我们看到了4.1.0.RELEASE版本似乎还不错,其依赖的spring版本在4.2.5.RELEASE:
因此我们将这个版本的spring-security-web填入pom.xml看一下效果,确实已经没有依赖冲突产生了:
如果我们找不到完美匹配4.2.5.RELEASE的spring-security-web怎么办,比如所有的spring-security-web版本就是在4.2.3.RELEASE或者4.2.6.RELEASE,那么我们就得想到妥协一下了:使用4.1.1.RELEASE版本的spring-security-web,它的spring依赖版本是4.3.1.RELEASE,
那么我们试图使用exclusive标签来忽略spring版本:
org.springframework.security spring-security-web 4.1.1.RELEASE spring-aop org.springframework spring-beans org.springframework spring-context org.springframework spring-core org.springframework spring-expression org.springframework spring-web org.springframework
依赖冲突会消失,spring-security-web会使用4.2.5.RELEASE版本的spring:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/69453.html
摘要:添加的的依赖,可以从项目的中拷贝使用命令编译项目。在子模块中我们可以这样使用引入父模块坐标三使用建立项目新建一个项目,选择,如图所示在中配置插件可参见官方文档。部署项目到即可。 一、Maven入门 1.下载maven Maven是基于项目对象模型(Project Object Model),可以通过一小段描述信息来管理项目的构建、报告和文档的项目管理工具,提供了一个仓库的概念,统一...
摘要:时间年月日星期二说明本文部分内容均来自慕课网。项目一个项目代表一个正在构建的组件比如一个文件,当构建启动后,会基于实例化一个类,并且能够通过变量使其隐式可用。任务动作定义了一个最小的工作单元。 时间:2017年05月16日星期二说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:无个人学习源码:https://github.com/zccod...
摘要:在平常工作中我们经常会遇到引用的包冲突的事情,这时候我们就需要找出冲突的包,并将低版本或者缺少某些方法的给剔除掉。要选择冲突项的话可以直接点击,然后在点击,显示的会更清楚一些,因为包比较多,依赖比较复杂会让图变得很小。 在平常工作中我们经常会遇到maven引用的jar包冲突的事情,这时候我们就需要找出冲突的包,并将低版本或者缺少某些方法的jar给剔除掉。这个时候使用idea自带...
阅读 1936·2021-10-25 09:48
阅读 2745·2021-09-22 14:59
阅读 1672·2019-08-29 16:52
阅读 826·2019-08-29 16:07
阅读 2279·2019-08-29 12:38
阅读 1733·2019-08-26 13:23
阅读 858·2019-08-26 11:49
阅读 3186·2019-08-26 10:56