在 maven 项目中,所有依赖通常都在 pom.xml 中通过 dependency 声明。但并不是所有依赖在项目生命周期的各个阶段都需要使用。例如,有些依赖只在 编译阶段使用,有些只在 运行阶段使用,还有一些只在 测试阶段使用。
为了解决这一问题,maven 提供了 依赖作用域(dependency scope) 机制。scope 用于定义依赖在 编译、运行、测试和打包阶段是否生效,从而决定该依赖是否会被加入到对应阶段的 类路径(classpath) 中。如果不显式指定 scope,默认值为:
一、maven 的依赖管理机制
在 maven 项目中,所有依赖都通过 pom.xml 文件声明,例如:
<dependencies>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-context</artifactid>
<version>6.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies> 如果不显式指定 scope,默认值为:
compile
当 maven 构建项目时,会自动完成以下工作:
- 读取
pom.xml中定义的依赖 - 从远程仓库下载依赖
- 将依赖缓存到本地仓库
本地仓库位置:
~/.m2/repository
随后 maven 会在 不同构建阶段 将这些依赖加入不同的类路径中。
二、什么是类路径(classpath)
在 java 中,类路径(classpath) 是 jvm 或 java 编译器用于查找 .class 文件和依赖库的位置集合。
简单来说:
类路径就是 java 程序在运行或编译时,用来查找类文件的路径列表。
类路径通常包含以下几种资源:
- 项目编译后的
.class文件 - 第三方依赖库(jar)
- 项目资源文件(resources)
如果某个类不在类路径中,程序就会出现典型错误:
classnotfoundexception noclassdeffounderror
而 maven 的核心作用之一,就是 自动管理这些类路径依赖。
三、maven 常见的五种 scope
maven 常见的依赖作用域主要包括以下几种。
1 compile(默认作用域)
compile 是 maven 的 默认作用域,如果不写 scope,依赖默认就是 compile。
特点:
- 编译阶段可用
- 运行阶段可用
- 测试阶段可用
- 打包时会被包含
例如:
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-context</artifactid>
</dependency>spring 框架依赖通常就是 compile。
适用于:
- 项目核心依赖
- 应用运行必须依赖的库
2 provided
provided 表示 编译时需要,但运行时由外部环境提供。
特点:
- 编译阶段可用
- 运行阶段不可用
- 不会被打包
典型例子:
servlet api
例如:
<dependency>
<groupid>jakarta.servlet</groupid>
<artifactid>jakarta.servlet-api</artifactid>
<scope>provided</scope>
</dependency>原因是:
tomcat / jetty 已经提供 servlet api
如果再打包进去就会冲突。
3 runtime
runtime 表示 编译时不需要,但运行时需要。
特点:
- 编译阶段不可用
- 运行阶段可用
- 会被打包
典型例子:
jdbc驱动
例如:
<dependency>
<groupid>mysql</groupid>
<artifactid>mysql-connector-j</artifactid>
<scope>runtime</scope>
</dependency>原因:
编译代码只依赖:
java.sql
但运行数据库时需要:
java.sql
4 test
test 作用域只在 测试阶段生效。
特点:
- 编译主代码不可用
- 运行主程序不可用
- 仅在测试代码中可用
例如:
<dependency>
<groupid>org.junit.jupiter</groupid>
<artifactid>junit-jupiter</artifactid>
<scope>test</scope>
</dependency>适用于:
junit mockito testng
这些库只在测试时使用。
5 system
system 依赖是 maven 早期提供的一种方式,用于 引用本地 jar 包。
例如:
<dependency>
<groupid>example</groupid>
<artifactid>example-lib</artifactid>
<scope>system</scope>
<systempath>d:/libs/example.jar</systempath>
</dependency>缺点:
- 不参与 maven 依赖管理
- 不可移植
因此 基本不推荐使用。
四、maven scope 与类路径关系
maven 在构建项目时,会根据 scope 决定依赖是否加入不同阶段的 classpath。
| scope | 编译 | 运行 | 测试 | 打包 |
|---|---|---|---|---|
| compile | ✔ | ✔ | ✔ | ✔ |
| provided | ✔ | ✘ | ✔ | ✘ |
| runtime | ✘ | ✔ | ✔ | ✔ |
| test | ✘ | ✘ | ✔ | ✘ |
因此可以这样理解:
maven 会根据
pom.xml中依赖的scope,在 编译、运行和打包阶段构建不同的 classpath,从而决定哪些依赖在不同阶段被引入。
到此这篇关于maven 依赖作用域详解:compile、provided、runtime、test的文章就介绍到这了,更多相关maven 依赖作用域内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论