xiaoming728

xiaoming728

Maven依赖范围scope详解

23
2024-01-12
Maven依赖范围scope详解

来源:CSDN - liaowenxiong

发布: 2022-12-10 10:38:28

链接:https://blog.csdn.net/liaowenxiong/article/details/122350988

一、依赖范围

maven 项目不同的阶段引入到classpath中的依赖是不同的。

例如:
编译时,maven 会将与编译相关的依赖引入classpath中;
测试时,maven会将测试相关的的依赖引入到classpath中;
运行时,maven会将与运行相关的依赖引入classpath中。

依赖范围就是用来控制依赖与三种classpath(编译classpath、测试classpath、运行classpath)的关系。 依赖范围更为通俗的理解,其实就是给依赖包打标记,例如:将 A 依赖包标记为“compile”,Maven 就知道 A 依赖包在项目编译的时候要被引入到 classpath 中。

依赖范围必须在 pom.xml 文件中的 <scope> 标签中设定,如下所示:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.7</version>
  <scope>test</scope>
</dependency>

上述 <scope> 标签就是用来指定被依赖资源的依赖范围,可选配置有 compile、test、provided、runtime、system、import,若不指定则默认 compile。

在 pom.xml 中设定好后,你需要点击“Load Maven Changes” 才会生效。

比方说,你修改了标签 <scope> 的取值,你需要 Load Maven Changes,在模块的依赖管理中才会出现新的取值,如下所示:

你如果只是在上述依赖管理的界面中改变 scope 的取值是没有效果的,只能通过 pom.xml 中的 scope 标签来设定。

说明:

  1. 编译是指将整个项目(其实是模块)的 src/main/java 目录下的源代码文件以及 resources 目录下的资源文件编译输出到 classes 目录下。在这个编译过程中编译器会到 classpath 指定的目录下查找字节码文件(jar包、class文件等)

  2. 测试是指编译测试的代码和运行测试的代码,通常使用 Junit 工具进行代码的测试

  3. 运行是指项目部署到服务器,并且启动了服务器,客户端可以正常访问应用

1、compile

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

既然运行时也要使用 scope 设为 compile 的依赖,所以 scope 为 compile 的依赖在项目打部署包的时候(即构建 artifact)会被一起打包,会放在 WEB-INF/lib 目录下。

2、test

测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子是JUnit,它只有在编译测试代码及运行测试的时候才需要。

scope 为 test 的依赖只在测试时使用,用于编译和运行测试代码,不会参与项目的打包。

3、provided

已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效(对运行的classpath无效)。典型的例子是 servlet-api, 编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引人一遍。既然运行时容器会提供,所以 scope 为 provided 的依赖不会参与项目的打包。

4、runtime

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

既然运行时也要使用 scope 设为 runtime 的依赖,所以 scope 为 runtime 的依赖在项目打部署包的时候(即构建 artifact)会被一起打包,会放在 WEB-INF/lib 目录下。

5、system

系统依赖范围。该依赖与三种 classpath 的关系,和 provided 依赖范围完全一致。但是,system 范围的依赖不会从 maven 仓库下载,而是从本地文件系统获取,使用 system 范围的依赖时必须通过 <systemPath> 元素显式地指定依赖文件的路径。

由于此类依赖不是通过 Maven 仓库解析的,而且往往与本机系统绑定,可能造成构建(构建的产物有:classes和artifact)的不可移植,因此应该谨慎使用。

元素 <systemPath> 可以引用环境变量,如下:

<dependency>
	<groupId>javax.sql</groupId>
	<artifactId>jdbc-stext</artifactId>
	<version>2.0</version>
	<scope>system</scope>
	<systemPath>${java.home}/lib/rt.jar</systemPath> 
</dependency>

6、import

导入依赖范围,该依赖范围不会对三种 classpath 产生影响,该依赖范围只能与 <dependencyManagement> 元素配合使用,其功能为将目标pom.xml 文件中元素 <dependencyManagement> 的配置导入合并到当前 pom.xml 文件的元素 <dependencyManagement> 中。有关元素 <dependencyManagement> 的功能请了解 Maven 继承特性。

二、依赖传递

依赖传递就是假设你有一个 Maven 项目叫 A,你在这个项目中添加了一个依赖,这个依赖是你的另一个 Maven 项目 B,你在这个被依赖的项目 B 中添加一些依赖,这些依赖也会自动地添加到 A 中,这就是依赖传递。简单来说就是项目的依赖的依赖也会成为该项目的依赖。

<scope> 标签的取值对依赖传递有什么影响呢?这个影响就是,只有当依赖的 scope 标签被定义为 compile 时才会发生依赖传递,而定义为 test 或者 provided 都不会发生依赖传递。

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

三、参考资料

https://www.pianshen.com/article/90681857024/

https://www.liaoxuefeng.com/wiki/1252599548343744/1309301178105890

https://www.cnblogs.com/sanshisiniao/articles/12068847.html

https://www.cnblogs.com/tuyang1129/p/10741558.html

https://blog.csdn.net/seasonsbin/article/details/79093647

https://blog.csdn.net/lishuoboy/article/details/100554751