maven的依赖传递

  • Post author:
  • Post category:其他


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生效。



版权声明:本文为JavaWeb_Hao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。