1.何为传递性依赖:
项目A--B--C :A依赖B,B依赖C,那么B对于A就是第一直接依赖,C对于B就是第二直接依赖关系,C对于A就是所谓的传递性依赖。
2.传递性依赖和依赖范围:
当第二直接依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致;当第二直接依赖的范围是test的时候,依赖不会得以传递;
当第二直接依赖的范围是provided时,只传递第一直接依赖范围也为provided的依赖,且传递性依赖的范围同样为provided;当第二直接依赖的范围
是runtime时,传递性依赖的范围与第一直接依赖的范围一致,但compile例外,此时传递 性依赖范围为runtime。
3.依赖的调解:
除了关心直接依赖,当传递性依赖发生冲突时,就需要知道冲突的传递性依赖是从什么路径引入的。
(1)依赖调解第一原则:路径最近者优先
例:项目A-->B-->C-->X(1.0) 项目A-->D-->X(2.0) X(2.0)会被解析使用。
(2)依赖调解第二原则:在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用,顺序最靠前的那个依赖优胜。
例:项目A-->B-->Y(1.0) 项目A-->C-->Y(2.0) 如果B的依赖声明在C之前,那么Y(1.0)就会被解析使用。
4.排除依赖:
项目A-->B-->C 如果不想引入传递性依赖C,可以显示地声明对于项目C 特定版本的依赖。使用exclusions元素声明排除依赖,exclusions可以包含一个或多个exclusion子元素,因此可以排除一个或多个传递性依赖。声明exclusion时只需要groupId和artifactId,不需要version元素。
A|-->B-|->C(??) 排除对C的传递性依赖
|-->C(version 1.1.0) 直接增加特定版本的C依赖
5.优化依赖:
在项目中使用 mvn dependency:list 命令查看当前项目的已解析依赖。 使用 mvn dependency:tree 命令查看依赖树。
在项目中使用 mvn dependency:analyze 命令分析当前项目的依赖,只会分析编译主代码和测试主代码使用的依赖。其中结果中标明 Used
undeclared dependencies,意指项目中使用的,但没有在POM中配置的依赖即没有显示声明的依赖,该依赖可能存在风险。例如该例中可能项目A
中的一些类有关于项目C的Java import声明,但C这个依赖实际是通过传递性依赖进入classpath的,这就意味者潜在的风险。一般来说我们对直接依
赖的版本变化会比较清楚,因为那是我们自己直接配置的,但对于传递性依赖的版本变化,就会比较模糊,当这种变化造成构建失败的时候,就很难找
到原因。因此我们应当增加这些 Used undeclared dependencies 。依赖分析还提供了 Unused declared dependencies 供我们参考,这表示那些
我们配置了,但并未直接使用的依赖。需要注意的时,对于这些依赖,我们不该直接简单地删除。由于dependency:analyze只分析编译主代码和测试
代码使用的依赖,一些执行测试和运行时的依赖它发现不了,因此还需要人工分析。通常情况,Unused declared dependencies 还是能帮助我们发
现一些无用的依赖配置。