scope范围
名称 | 有效范围 |
---|---|
Compile | 编译,测试,运行。默认的依赖范围 |
Test | 测试,如Junit |
Runtime | 运行,如JDBC |
Provided | 编译,测试,如ServletAPI |
System | 编译,测试,依赖于系统变量 |
compile
maven默认的范围就是compile,在所有的classpath中可用,同时它们也会被打包。
provided依赖只有在当JDK或者一个容器已经提供该依赖之后才使用。例如:开发了一个web应用,你可能在编辑classpath中需要使用servlet API来编辑一个servlet,但是你不会想要在打包更好的WAR中包含这个servlet API,因为该API由同期或者JDK直接提供。该范围的依赖不存在传递性,也不会被打包。
runtime在运行和测试系统时需要,但是在编辑时不需要,比如:可能在编辑的时候只需要JDBC API JAR ,只有在运行的时候才需要JDBC驱动的实现。
test编辑和测试的时候使用。
system范围依赖与provided类似,但是你必须显式的提供一个对于本地系统中JAR文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构建应该是一直可用的,Maven 也不会在仓库中去寻找它。如果你将一个依赖范围设置成系统范围,你必须同时提供一个
systemPath
元素。注意该范围是不推荐使用的(建议尽量去从公共或定制的 Maven 仓库中引用依赖)。示例如下:
<project>
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
…
</dependencies>
</project>
依赖传递
说明:
第一列是A对B的依赖,第一行是B对C的依赖
-
当B对C的依赖的scope是
test
或者
provided
,则A不依赖C。 -
当B对C的依赖是scope是
runtime
或者
compile
,则A依赖C。且传递依赖的scope的
规则:
如果A对B的依赖是compile,那么A对C的依赖和B对C的依赖相同,否则和A对B的依赖保持一致
依赖传递:A依赖B,B依赖C,那么A依赖C
上面描述没有问题的。但是有时候C中设定的依赖版本,但是在A中并查看依赖的版本,并非是C中设定的依赖版本,一直以来都感觉这是maven的bug,但实际上是我之前错了,在传递依赖的时候版本也有一定的规则。
依赖传递的规则,以mysql的5.1.45以及8.0.11为例:
1、在本模块B的pom声明了版本,则mysql版本即为此处指定的版本。
2、为同一个pom中声明了两次mysql这两个版本,谁在下面谁生效
3、父模块A中声明了mysql版本,使用dependencyManagement设定了版本,并且在引用的地方B模块并未指明版本,则以B中引用过来的B的版本就是A中设定的版本并非是C本身自己的版本。
4、依赖距离的问题
(1)长度相同
上面:B依赖C
又有一个依赖:B依赖D
C和D中都有对mysql不同版本的引用。
C和D到B的长度相同,那么这个时候B的pom中谁的依赖在前面谁生效。
(2)长度不相同
上面:B依赖C
又有一个依赖:B依赖E,E依赖 D
C和D中都有对mysql不同版本的引用。
C和D到B的长度不相同,那么这个时候谁离B短谁生效,此处很明显就是C生效。