Maven笔记之依赖范围

依赖范围

  • compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-core,在编译、测试、运行的时候都需要使用该依赖。
  • test:测试范围依赖。使用此依赖范围的Maven依赖,只对测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此依赖。典型的例子就是Junit,它只有在编译测试代码及运行测试的时候才需要。
  • provided:已提供依赖范围。使用此依赖范围的Maven依赖,只对编译和测试classpath有效,但在运行时无效。典型的例子就是servlet-api,编译和测试的项目的时候需要改依赖,但在运行项目的时候,容器已经提供,就不在需要Maven重复地引入一遍。
  • runtime:运行时范围依赖。使用此依赖范围的Maven依赖,只对运行和测试classpath有效,但在编译主代码时无效。典型的例子就是jdbc驱动实现,项目主代码在编译只需要JDK提供的JDBC接口,只有在执行测试和运行项目的时候才需要实现上述接口的具体JDBC驱动。
  • system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围依赖时必须通过systemPath元素显式的指定依赖文件的路径。由于此依赖不是通过Maven仓库解析的,而且往往与本机系统相绑定,可能早就系统的不可移植,应该谨慎使用。
  • import:导入依赖范围。该依赖范围不会对三种classpath产生实际的影响。因为该元素在dependencyManagement元素下才有效dependencyManagement元素下的依赖声明不会引入实际的依赖,不过它能够约束dependencies下的依赖使用)
依赖范围与classpath的关系

依赖范围(Scope)

对于编译classpath有效 对于测试classpath有效 对于运行classpath有效
compile Y Y Y
test - Y --
provided Y Y --
runtime - Y Y
system Y Y --

 

传递性依赖

如下图,最左边第一行表示第一直接依赖范围,最上面第一行表示第二直接依赖范围,中间交叉单元格则表示传递性依赖范围

  compile test provided runtime

compile

compile -- -- runtime
test test -- -- test
provided provided -- provided provided
runtime runtime -- -- runtime

依赖调解

有时候,当传递性依赖造成问题的时候,我们就需要清楚地知道该传递性依赖是从哪条依赖路径引入的。

例如:A-->B-->C--X(1.0),A-->D-->X(2.0)

X是A的传递性依赖,但是两条依赖路径上有两个版本的X,这个时候两个都解析是不对的,那样会造成依赖重复,因为必须选择一个。

Maven依赖调解的第一原则:路径最近者优先。上面例子中X(1.0)的路径长为3,X(2.0)的路径长为2,因此2.0会被解析使用。

如果两个依赖长度一样。

Maven依赖调解的第二原则:第一声明者优先。在依赖长度相同的情况下,在POM中依赖声明的顺序决定了谁会被解析使用,顺序靠前的那个优先被依赖

可选依赖

可选性依赖不会得到传递。

例如:A-->B,B-->X(可选),B-->Y(可选)

由于这里的X和Y依赖是可选的,所以依赖不会被传递。下面声明一个可选性依赖:

<dependency>
    <group>mysql</group>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.10</version>
    <optional>true</optional>
</dependency>

当项目中要使用可选性依赖的时候,需要显示声明。

排除依赖

传递性依赖会给项目隐式的映入很多依赖,这极大的简化了项目依赖管理,但是有些时候这种特性会带来很多问题。

例如,当前项目引用了一个第三方依赖,而这个第三方依赖由于某些原因依赖了另一个类库的SNAPSHOT版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,而SNAPSHOT的不稳定性会直接影响当前项目。另外想替换某个传递性依赖。这个时候就需要排除依赖,如下所示:

<dependencies>
    <dependency>
        <groupId>com.myapp</groupId>
        <artifactId>demo</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <groupId>com.a</groupId>
                <artifactId>project-a</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.a</groupId>
        <artifactId>project-a</artifactId>
        <version>2.0</version>
    </dependency>
</dependencies>

上面的例子排除了一个依赖project-a,并引用了一个其他版本的project-a。

猜你喜欢

转载自blog.csdn.net/weixin_39032575/article/details/81201875