Maven(二)

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的依赖范围和传递关系。

相关推荐
野犬寒鸦14 分钟前
从零起步学习Redis || 第四章:Cache Aside Pattern(旁路缓存模式)以及优化策略
java·数据库·redis·后端·spring·缓存
白水先森33 分钟前
C语言作用域与数组详解
java·数据结构·算法
豆浆whisky1 小时前
netpoll性能调优:Go网络编程的隐藏利器|Go语言进阶(8)
开发语言·网络·后端·golang·go
蓝天白云下遛狗1 小时前
go环境的安装
开发语言·后端·golang
CAir21 小时前
go协程的前世今生
开发语言·golang·协程
@大迁世界1 小时前
Go 会成为“老生态”的新引擎吗?
开发语言·后端·golang
Absinthe_苦艾酒1 小时前
golang基础语法(六)Map
开发语言·后端·golang
-睡到自然醒~1 小时前
Golang 中的字符串:常见错误和最佳实践
开发语言·后端·golang
予非池物1 小时前
ubuntu安装go
开发语言·后端·golang
视睿2 小时前
【C++练习】06.输出100以内的所有素数
开发语言·c++·算法·机器人·无人机