Mvane的依赖范围
Maven 的依赖范围(Dependency Scope)用于精确控制依赖项在项目构建生命周期中的使用阶段和传递性,是避免依赖冲突和优化构建的关键配置。
Scope | 是否参与编译 | 是否参与测试 | 是否打包 | 是否传递 | 典型应用场景 |
---|---|---|---|---|---|
compile |
✅ | ✅ | ✅ | ✅ | 核心依赖(如 Spring Core、Lombok) |
provided |
✅ | ✅ | ❌ | ❌ | 容器/运行时提供的依赖(如 Servlet API) |
runtime |
❌ | ✅ | ✅ | ✅ | 运行时需但编译不需的依赖(如 JDBC 驱动) |
test |
❌ | ✅ | ❌ | ❌ | 测试专用库(如 JUnit、Mockito) |
system |
✅ | ✅ | ✅ | ❌ | 本地系统路径的依赖(不推荐使用) |
import |
- | - | - | - | 仅用于 <dependencyManagement> |
其实也就是我们在引入依赖的时候可选的<scope>标签,在这里面填写依赖的范围如下:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<!-- 就是这个--!>
<scope>provided</scope>
</dependency>
其他的都还好理解,一般来说我们也不会去填写,高级的特性也就是最后一个improt这个范围,import
是 Maven 依赖范围中最特殊 的一种,它仅用于 <dependencyManagement>
部分,专门用来继承第三方项目的依赖管理配置(如 Spring Boot 或 Dubbo 的 POM 文件)。
特性 | 说明 |
---|---|
唯一用途 | 仅在 <dependencyManagement> 中生效,用于导入第三方 POM 的依赖管理配置 |
非传统依赖范围 | 不参与编译、测试、打包,仅做依赖版本管理 |
依赖传递性 | 无传递性(不会引入实际依赖) |
典型应用场景 | 统一管理多模块项目或生态系统的依赖版本(如 Spring Cloud 版本对齐) |
这个有什么作用呢?一般就是用来进行版本管理的,这个其实和继承有点类似,但是区别也是很明显的,因为导入只会导入<dependencyManagement>
中的内容,而且导入后还必须声明依赖不然这个依赖也不回被导入,就比如Bpom有个a依赖版本是1,Apom导入了Bpom,如果不在<dependencies>(Apom中<dependencyManagement>外的
<dependencies>才行)中声明a依赖也是没有用的不会真正导入。如果声明了依赖没声明版本就会默认使用Bpom中的版本,如果声明了版本就会使用A的。
特性 | 继承 (<parent> ) |
导入 (<scope>import ) |
---|---|---|
语法 | 在 POM 中声明 <parent> |
在 <dependencyManagement> 中声明 import |
继承内容 | 父 POM 的所有配置(依赖、插件、属性等) | 仅合并目标 POM 的 <dependencyManagement> |
多继承支持 | ❌ 只能单继承 | ✅ 可导入多个 BOM |
依赖传递 | 父 POM 的普通 <dependencies> 会传递 |
仅版本管理,需显式声明依赖 |
插件配置 | 继承父 POM 的 <build> 配置 |
❌ 不继承插件 |
适用场景 | 统一项目结构、共享插件/资源 | 集中管理依赖版本(如 Spring Boot BOM) |
<project>
<dependencyManagement>
<dependencies>
<!-- 导入 B 的 dependencyManagement -->
<dependency>
<groupId>com.example</groupId>
<artifactId>B</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
#也可以在这里声明版本,这个声明的上下没关系,只要在Apom的dependencyManagement中声明了就不会使用Bpom的版本,当然还是要在外面声明依赖,不然依赖还是不会被引入
<dependency>
<groupId>com.example</groupId>
<artifactId>a</artifactId>
<version>1</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 必须显式声明依赖才会引入 -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>a</artifactId>
<!-- 版本从 B 继承 -->
</dependency>
</dependencies>
</project>
所以从这些看来,这个<dependencyManagement>标签只是用来统一管理版本的,其他的作用几乎没有用了,要注意的是<dependencyManagement>中定义的依赖的范围、排除、包含什么的标签也是会被导入到Apom的,反正记住只会导入<dependencyManagement>标签中的东西就对了。
Maven的依赖传递
我们上一篇已经说过了A依赖B依赖C这个C是怎么导入的,现在我们需要结合今天的依赖范围来重新认识一下,也就是不同的依赖范围会决定会不会引入C依赖,就比如B依赖的C使用的是provided范围,那么B是不会报错的,但是A使用B的时候如果用到了C那么就会报错,因为C并没有被传递进来。但是一般情况下大家使用的也是默认的依赖范围compile。

还有个最短路径优先的问题,在上面这个图中C 的 1.0 版本会被选中(路径更短),那如果两个路径一样长那么就会出现依赖冲突了,需要我们手动解决了,我们可以显示声明,也可以使用importPOM文件进行统一管理版本。
#查看依赖树形结构
mvn dependency:tree
#分析依赖冲突
mvn dependency:tree -Dverbose
我们可以使用上面的命令来查看依赖的树形结构,以及通过命令来查看依赖的冲突。就像下面这样可以查看依赖的树形结构以及每个依赖的范围是怎么样的。分析依赖冲突的这边就不演示了,相比前者就是信息更加充分。

总结
本篇主要讲了Maven的依赖范围和传递关系。