Maven之scope详解

本文最后更新于:2022年11月4日 上午

Maven中使用 scope 来指定当前包的依赖范围和依赖的传递性。常见的可选值有:compile, provided, runtime, test, system 等。scope 主要是用在 pom.xml 文件中的依赖定义部分,例如:

1
2
3
4
5
6
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.1.RELEASE</version>
<scope>test</scope>
</dependency>

scope各种取值详解

scope取值 有效范围(compile, runtime, test) 依赖传递 例子
compile all spring-core
provided compile, test servlet-api
runtime runtime, test JDBC驱动
test test JUnit
system compile, test

正如上表所示,

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仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。

systemPath元素可以引用环境变量。例如:

1
2
3
4
5
6
7
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>

scope的依赖传递

A–>B–>C。当前项目为A,A依赖于B,B依赖于C。知道B在A项目中的scope,那么怎么知道C在A中的scope呢?

答案是:

当C是test或者provided时,C直接被丢弃,A不依赖C; 否则A依赖C,C的scope继承于B的scope。

scope的值官方解释

  • compile This is the default scope, used if none is specified. Compile dependencies are available in all classpaths of a project. Furthermore, those dependencies are propagated to dependent projects.
  • provided This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
  • runtime This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
  • test This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases. This scope is not transitive.
  • system This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
    import (only available in Maven 2.0.9 or later)
    This scope is only supported on a dependency of type pom in the section. It indicates the dependency to be replaced with the effective list of dependencies in the specified POM’s section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.

References


Maven之scope详解
https://baymax55.github.io/2022/11/04/maven/Maven之scope详解/
作者
baymax55
发布于
2022年11月4日
许可协议