在SpringBoot开发时,我们一般使用maven作为项目的管理和构建工具。
一般情况下,我们都是通过以下方式引入一个依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
以上三个依赖有没有发现,有些有scope
属性,有些没有scope
属性,而且scope
属性的值也不一样。
概述
Maven中使用scope
来指定当前包的依赖范围和依赖的传递性。常见的可选值有:compile
,provided
,runtime
,test
,system
等。
所谓依赖范围,可以理解为项目的阶段,比如是在编译、测试、运行、打包哪个阶段有效。
所谓传递性,是指项目依赖关系的传递。比如当前项目为A,A依赖于B,B依赖于C。知道B在A项目中的scope,那么怎么知道C在A中的scope呢?
属性值 | 编译 | 调试 | 运行 | 打包 | 传递性 | 示例 | 备注 |
---|---|---|---|---|---|---|---|
compile | 是 | 是 | 是 | 是 | 是 | 无 | 无 |
test | 否 | 是 | 否 | 否 | 否 | junit | 测试代码的编译和执行,不会被打包 |
runtime | 否 | 是 | 是 | 是 | 是 | JDBC驱动 | 无 |
provided | 是 | 是 | 是 | 否 | 否 | lombok | provided意味着打包的时候可以不用包进去,别的设施(Web Container)会提供 |
system | 是 | 是 | 是 | 否 | 是 | 本地jar包 | 同provided,不过被依赖项不会从maven仓库抓,而是从本地文件系统拿,一定需要配合systemPath属性使用。不推荐使用system依赖。 |
import | 否 | 否 | 否 | 否 | 否 | 无 | 无 |
scope各种取值详解
compile
默认的依赖有效范围。如果在定义依赖关系的时候,没有明确指定依赖有效范围的话,则默认采用该依赖有效范围。
此种依赖,在编译、运行、测试时均有效。
provided
在编译、测试时有效,但是在运行时无效。provided
意味着打包的时候可以不用包进去,别的设施(Web Container)会提供。
事实上该依赖理论上可以参与编译,测试,运行等周期。相当于compile
,但是在打包阶段做了exclude
的动作。
例如:servlet-api,运行项目时,容器已经提供,就不需要Maven重复地引入一遍了。
runtime
在运行、测试时有效,但是在编译代码时无效。
说实话在终端的项目(非开源,企业内部系统)中,和compile
区别不是很大。比较常见的如JSR×××的实现,对应的API jar是compile
的,具体实现是runtime
的,compile
只需要知道接口就足够了。
例如:JDBC驱动实现,项目代码编译只需要JDK提供的JDBC接口,只有在测试或运行项目时才需要实现上述接口的具体JDBC驱动。
另外runntime
的依赖通常和optional
搭配使用,optional
为true
。我可以用A实现,也可以用B实现。
test
只在测试时有效,包括测试代码的编译,执行。例如:JUnit。
PS: test
表示只能在src
下的test
文件夹下面才可以使用,你如果在a项目中引入了这个依赖,在b项目引入了a项目作为依赖,在b项目中这个注解不会生效,因为scope为test
时无法传递依赖。
system
在编译、测试时有效,但是在运行时无效。
和provided
的区别是,使用system
范围的依赖时必须通过systemPath
元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。
scope的依赖传递
当前项目为A,A依赖于B,B依赖于C。知道B在A项目中的scope,那么怎么知道C在A中的scope呢?
答案是:
当C是test
或者provided
时,C直接被丢弃,A不依赖C; 否则A依赖C,C的scope继承于B的scope。
评论 (0)