一、前言
大家在处理maven依赖时,肯定都有遇到过包冲突的问题,其中最常见的就是在多级依赖时,会同时引入一个jar包的不同版本,导致在运行时出现NoSuchMethodError的错误,那么大家肯定会好奇对于这些情况maven是怎么去选择版本的呢?其中网上挺多文章已经都解密了它的处理方式,我这里先把这些方式抛出来,然后一个个的去验证它们。
当一个项目中出现重复的依赖包时,maven 2.0.9之后的版本会用如下的规则来决定使用哪一个版本的包:
1、最短路径原则
2、声明优先原则
3、同级依赖后加载覆盖先加载
二、分析与验证
准备:创建一个验证工程已经多个验证模块,并根据校验场景来引入依赖关系,其中作为验证对象的testD构建两个不同版本(1.0和2.0)的jar
1、最短路径原则
分析
对于服务A直接依赖了服务B和E,其中B和E都直接或间接的引用了D的两个版本1.0和2.0,此时根据最短路径原则,A最终引用的应该是D的2.0版本
验证
按照上图的依赖关系进行模块依赖
其中C依赖了D的1.0版本,E依赖了D的2.0版本,通对A执行mvn dependency:tree 命令来分析A的依赖树
通过依赖树结果来看,最终依赖的是D的2.0版本,所以验证了maven的最短路径原则;
2、声明优先原则
分析
A服务依赖C和E,其中C依赖D的1.0版本,E依赖D的2.0版本,其中C已依赖声明在E之前,此时根据声明优先原则,相同的依赖路径,会安装依赖引入的先后顺序进行选择,选择最先引入的版本,所以应该是选择1.0版本;
将E和C的依赖顺序交换,此次应该选择的是D的2.0版本
验证
A服务依赖C和E,其中C依赖D的1.0版本,E依赖D的2.0版本,其中C已依赖声明在E之前,通对A执行mvn dependency:tree 命令来分析A的依赖树,最终引入的是D的1.0版本
将E和C的依赖顺序交换,通对A执行mvn dependency:tree 命令来分析A的依赖树,最终引入的是D的2.0版本,所以验证了声明优先原则;
3、同级依赖,后加载覆盖先加载
A直接依赖D的1.0和2.0版本,1.0的依赖声明顺序早于2.0版本,此时2.0版本会覆盖1.0版本从而最终选择2.0版本;
交换1.0和2.0的依赖声明顺序,2.0早于1.0,此时1.0版本会覆盖2.0版本,从而最终选择2.0版本
验证
A直接依赖D的1.0和2.0版本,1.0的依赖声明顺序早于2.0版本,通对A执行mvn dependency:tree 命令来分析A的依赖树,最终引入的是D的2.0版本
交换1.0和2.0的依赖声明顺序,2.0早于1.0,通对A执行mvn dependency:tree 命令来分析A的依赖树,最终引入的是D的1.0版本,从而最终验证了本级依赖中,后加载的依赖会覆盖先加载的依赖;
三、总结
通过上述的说明和验证,最终得出maven对重复依赖的版本处理方式为:
1、最短路径原则:对于多级依赖出现相同jar的不同版本,maven会选择路径最短的依赖;
2、声明优先原则:对于多级依赖出现相同jar的不同版本,并且所经历的路径相同时,maven会选择最先声明的依赖版本;
3、同级依赖,后声明会覆盖先声明原则:对于同一级的依赖出现相同jar的不同版本,maven会根据依赖声明的先后顺序,选择后声明的依赖版本;