maven依赖范围及依赖传递

如题所述

maven依赖范围是用于控制依赖与三种classpath(编译、测试、运行)之间的关系,maven提供了以下几种依赖范围:

compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-core,在编译、测试、运行时都需要使用该依赖。

test:测试依赖范围。使用此依赖范围的maven依赖,只对测试classpath有效,在编译主代码或运行项目时无法使用此类依赖。典型的例子就是junit,它只有在编译测试代码及运行测试时才需要。

provided:已提供依赖范围。使用此依赖范围的maven依赖对于编译和测试classpath有效,在运行时无效。典型的例子是servlet-api,编译和测试项目时需要该依赖,但在运行时容器已经提供,就不需要重复引入了。

runtime:运行时依赖范围。使用此依赖范围的maven依赖对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC的驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或运行项目时才需要实现上述接口的具体JDBC驱动。

system:系统依赖范围。该范围与三种classpath的关系和provided依赖范围完全一致。但是使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此依赖不是通过maven仓库解析而且与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。systemPath元素可以引用环境变量。

import:导入依赖范围。该依赖范围不会对三种classpath产生实际的影响。

依赖范围与classpath的关系如下:

maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入什么传递性依赖。但有时候,当传递性依赖造成问题时,我们就需要清楚地知道该传递性依赖是从哪条依赖路径引入的。

例如,项目A有这样的依赖关系:A-->B-->C-->X(1.0)、A-->D-->X(2.0),X是A的传递性依赖,但是两条依赖路径上有两个版本的X,那么哪个X会被maven解析使用呢?两个版本都被解析显然是不对的,因为那会造成依赖重复,因此必须选择一个。maven依赖调解的第一原则:路径最近者优先。该例中X(1.0)的路径长度为3,而X(2.0)的路径长度为2,因此X(2.0)会被解析使用。

依赖调解第一原则不能解决所有问题,比如这样的依赖关系:A-->B-->Y(1.0),A-->C-->Y(2.0),Y(1.0)和Y(2.0)的依赖路径长度是一样的,都为2。那么到底谁会被解析使用呢?在maven2.0.8及之前的版本中,这是不确定的,但是maven2.0.9开始,为了尽可能避免构建的不确定性,maven定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用。顺序最靠前的那个依赖优先。
温馨提示:内容为网友见解,仅供参考
无其他回答
相似回答
大家正在搜