依赖调停
Dependency Mediation | 依赖调停

传递性依赖是在
由于没有限制依赖的数量,如果出现循环依赖的时候会出现问题,这个时候有两种方式处理,一种是通过
依赖调节:如果在一个项目里面出现不同的模块,依赖了一个项目的不同版本的时候判断依赖的版本。
同一个A -> B -> C -> D 2.0 and A -> E -> D 1.0
。这就出现了冲突,你当然也可以再
Excluded & Optional Dependencies | 排除依赖于可选依赖
可选依赖使用的情况是对于某个依赖来说系统只有在某个特定的情况下使用到它。例如数据库驱动,有
排包
再次回顾下
- compile(默认使用
) :编译依赖范围,编译、测试、运行都生效; - test:测试依赖范围,只在测试的
classpath 有效,比如我们常用的JUnit ; - provided:只对编译和测试有效,对运行无效,常用于容器提供了的运行环境;
- runtime:运行时依赖范围,比如
JDBC 驱动,编译和测试时不需要,只需要使用JDK 提供的JDBC 接口; - system:系统依赖范围,依赖
Maven 仓库以外的依赖。
仲裁规则
- 第一原则:路径最短优先选中,将
pom 文件默认为一个树形结构,路径节点从根出发。
假设:路径
- 第二原则:先声明者优先原则
当路径长度相同时候,就要使用第二原则。假设:路径
- 第三原则:冲突
jar 句柄顺序随机原则
如果系统自己已经在
项目排包
mvn dependency:tree>tree.log
直接执行这个命令,基本上只能先优先看一下总体的依赖状况,做整体评估,然后根据系统日志报错信息反查。
-
启动时直接报错,
java.lang.ClassNotFoundException , 或者方法不存在:这种比较简单,直接查找该类在哪个包中,相互冲突的基本上在两个jar 包内就可以确定,基本手段:排除低版本,选择和自己Java 代码一致使用的,排除和业务代码无关的。 -
类路径长度统计,版本就高不就低。这点需要找到有疑似冲突的,做一个简单的统计,常常新版本的会解决之前的问题,但是也有一个潜在的风险,高版本的可能引入了更多有可能的冲突,因此,高版本的尽量遵循业务无关的类库,如果和业务有关,尽量把两个版本的依赖树都保存以做比对,或者和具体业务负责人确认改动点。
-
隐含错误加上调试参数:
mvn +X dependency:tree>tree.log
,这样根据报错信息可以更精确的定位到错误或者冲突。