Maven的依赖传递、依赖管理、依赖作用域

在Maven项目中通常会引入大量依赖,但依赖管理不当,会造成版本混乱冲突或者目标包臃肿。因此,我们以SpringBoot为例,从三方面探索依赖的使用规则。

1、 依赖传递

依赖是会传递的,依赖的依赖也会连带引入。例如在项目中引入了spring-boot-starter-web依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.18</version>
</dependency>

那么业务项目不仅直接引入了spring-boot-starter-web依赖,还间接引入了spring-boot-starter-web的依赖项:

spring-boot-starterspring-boot-starter-jsonspring-boot-starter-tomcatspring-webspring-webmvc

Maven依赖关系如下图所示:

其中,spring-boot-starter-web是直接依赖,spring-boot-starter-web的依赖项:spring-boot-starterspring-boot-starter-jsonspring-boot-starter-tomcatspring-webspring-webmvc为间接依赖。

2、依赖管理

2.1、dependencyManagement

maven中的dependencyManagement节点主要用来统一管理依赖项的版本号。如果依赖中,未指定版本号,则采用dependencyManagement引入的pom文件中的版本号。dependencyManagement只用来指定依赖的版本,不会真正引入依赖。

假如pom文件中引入了如下依赖:  

<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>3.3.1</version><scope>import</scope></dependency></dependencies>
</dependencyManagement>

那么在引入具体依赖时,可以不指定版本号:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

此时, spring-boot-starter-web会自动引入spring-boot-dependencies中指定的版本号3.3.1

2.2、parent

Maven 借鉴了面向对象中的继承思想,提出了 POM 继承思想。一个项目可通过继承父模块的 POM 来获得对相关依赖的声明。其目的是为了消除子模块 POM 中的重复配置,其中不包含有任何实际代码,因此父模块 POM 的打包类型(packaging)必须是 pom。

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version>
</parent>

此时,对于spring-boot-starter-web依赖,会自动引用spring-boot-starter-parent中指定的版本号2.7.18

2.3、dependency

对于普通的依赖,大家用的最多的也便是这种,在声明依赖时直接指定版本号:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.6.15</version>
</dependency>

这种方式最直观,但依赖过多时,不便于统一管理。 

2.4、依赖优先级

如果我们将上述三种方式混合使用,放在同一个项目中,且指定了不同的版本号,会产生什么效果呢?

 先展示结果如下图:

可以看到直接依赖spring-boot-starter-web的版本为2.6.15,但间接依赖spring-******的版本均为2.7.18。所以结论如下:

优先级:dependence指定版本 > parent指定版本 > dependencyManagement指定版本

dependence指定版本仅限于直接依赖的版本,间接依赖仍然采用parent所指定的版本,dependencyManagement指定的版本最次之。

3、 依赖作用域

在Maven中,可以使用scope来指定当前依赖项的作用域,常见的值有:compile、provided、runtime、test、import等。

3.1 compile

compile也是默认的作用域,如果引入依赖时,没有明确指定作用域,则依赖作用域为compile。

compile作用域的依赖,在编译、测试和运行时均有效,并参与项目的打包过程,该依赖会传递给依赖该模块的其他模块。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.6.15</version><scope>compile</scope>
</dependency>

3.2 provided

provided作用域的依赖,仅在编译和测试时有效,在运行时不可用,且不会参与项目的打包过程,也不会传递给引用项目。

例如,Lombok模块仅用于编译时生成相应的Contructor、Getter、Setter、ToString等方法,但在运行时并不需要这个依赖,因此通常指定为provided,打包后的目标文件中也不包含该依赖:

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope>
</dependency>

3.3 runtime

runtime作用域的依赖,在测试和运行时是可用的,但在编译时是不可用的,也会参与项目的打包过程,其依赖传递给引用该模块的项目。

runtime作用域的模块在编译时不可用,就说明该引用中的类在java代码中也不能直接使用,否则无法编译通过。

例如,mysql数据库驱动在代码中不需要直接调用,代码通常使用mybatis或者java.sql包下的类。因此引入依赖时,通常指定为runtime,在运行时,该驱动包直接注册到程序中:

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><scope>runtime</scope>
</dependency>

3.4 test

test作用域的依赖,仅在测试时可用(测试代码的编译和执行),其不会参与项目的打包过程,也不会传递给其他模块。

这些依赖中的类只能在src/test/java中使用,无法用于src/main/java中的代码。

测试相关的均属于此类,比如:spring-boot-starter-test、junit等:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

3.5 import

每个项目,一般都会继承自一个父项目,这个父项目可能是公司的一个基础项目,也可能是一个框架项目,比如开头提到的springboot:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version>
</parent>

这个父项目中,父项目的父项目是spring-boot-dependencies,spring-boot-dependencies中会使用dependencyManagement标签对依赖项的版本统一管理,子项目中,可以按需引入dependencyManagement中依赖即可,可以省略版本号。

但是Maven最多只能有一个parent项目,如果把所有的dependencyManagement都加入到parent项目中,又会导致parent项目太臃肿,依赖杂乱不好管理。因此,import作用域便可以解决这个问题。import可以通过非继承的方式批量引入另一个依赖项中。

说明:<scope>import</scope>只能用在dependencyManagement下type为pom的dependency中。

3.6 作用域总结

作用域编译时测试时运行时打包时传递性
compile
provided×××
runtime×
test××××
import×××

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/32824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶仿真测试用例表格示例 ACC ELK FCW

自动驾驶仿真测试用例表格示例 测试用例概览 本测试用例表格涵盖了自动驾驶系统中多个关键功能和场景的测试&#xff0c;旨在确保系统在不同条件下的表现和稳定性。 用例编号测试项目测试描述预期结果实际结果通过/失败TC-001ACC功能测试在高速公路上启用ACC&#xff0c;测试车…

SCI一区级 | Matlab实现BO-Transformer-LSTM多变量时间序列预测

SCI一区级 | Matlab实现BO-Transformer-LSTM多变量时间序列预测 目录 SCI一区级 | Matlab实现BO-Transformer-LSTM多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【SCI一区级】Matlab实现BO-Transformer-LSTM多变量时间序列预测&#xff0c;贝叶斯…

力扣SQL50 超过5名学生的课

Problem: 596. 超过5名学生的课 Code select class from courses group by class having count(distinct student) > 5;

高通安卓12-固件升级

下载步骤 第一步 格式化 「下载一次即可&#xff1b;能开机能下载的板子 忽略这一步&#xff0c;直接执行第二步即可」 QFIL工具配置为UFS类型&#xff0c;勾选Provision&#xff0c;如下图&#xff1a; Programmer选择prog_firehose_ddr.elf&#xff0c;Provision Xml选择prov…

【STM32-新建工程-CubeMX】

STM32-新建工程-CubeMX ■ CubeMX 生产工程 ■ CubeMX 生产工程

QT事件处理系统之五:自定义事件的发送案例 sendEvent和postEvent接口

1、案例 双击窗口,会发送 自定义事件,然后在事件过滤中心进行拦截处理自定义事件。 2、核心代码 /*解释:双击窗口时,将产生双击事件,然后该事件被包裹成一个对象,随后将会被发往event事件中心,然后进行事件的处理(Widget对象);因为m_lineEdit开启了事件过滤机制,所…

Linux - 利用/proc/sys/vm/drop_caches实现手工清理系统缓存

文章目录 现象buff/cache 的作用和含义分析 buff/cache 占用大量内存的原因是否需要清理缓存及其方法 命令清理缓存方法1. sync 命令2. echo 3>/proc/sys/vm/drop_caches 命令 注意事项小结 现象 使用free 命令&#xff0c;看到 buff/cache 占用很多 。 free 命令用于显示系…

第一个Flask程序

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 一切准备就绪&#xff0c;现在我们开始编写第一个Flask程序&#xff0c;由于是第一个Flask程序&#xff0c;当然要从最简单的“Hello World&#xff…

GPT-5大幅推迟?OpenAI CTO称将在2025年底到2026年初推出

GPT-5大幅推迟&#xff1f;OpenAI CTO称将在2025年底到2026年初推出 OpenAI CTO同时透露&#xff0c;GPT-5性能将有巨大飞跃&#xff0c;在某些特定任务中达到“博士水平”智能&#xff0c;此前市场曾预测GPT-5可能在2023年底或2024年夏季发布。 一再跳票的GPT-5可能大幅推迟…

JetBrains IDEA 新旧UI切换

JetBrains IDE 新旧UI切换 IntelliJ IDEA 的老 UI 以其经典的布局和稳定的性能&#xff0c;成为了许多开发者的首选。而新 UI 则在此基础上进行了全面的改进&#xff0c;带来了更加现代化、响应式和高效的用户体验。无论是新用户还是老用户&#xff0c;都可以通过了解和适应这…

101.qt qml-自定义日历控件2-附带动画效果

黑色风格截图如下所示: 白色风格如下所示: GIF效果如下所示: 1.控件使用介绍 QianWindow2.5版本及以上提供,源码位于:qrc:/common/qmlQianDateTime/QianCalendarInputField.qml QianWindow2.5版本及以上提供,示例使用代码位于:qrc:/pages/QianControlPages/QianDateTimeP…

修复:cannot execute binary file --- ppc64le 系统架构

前言&#xff1a; 修复node_exporter,引用pprof包&#xff0c;对源码编译后在 Linux 系统下执行程序运行时&#xff0c;发生了报错&#xff0c;报错信息&#xff1a;cannot execute binary file: Exec format error。 开始以为编译有问题&#xff0c;检查发现&#xff1b;该l…

C++ 教程 - 04 类的使用

文章目录 类的定义类定义案例 类的定义 C 在 C 语言的基础上增加面向对象编程&#xff0c;类是用于指定对象的形式&#xff0c;是一种用户自定义的数据类型&#xff0c;封装了数据和函数。类可以被看作是一种模板&#xff0c;可以用来创建具有相同属性和行为的多个对象。 cla…

python爬虫学习笔记一(基本概念urllib基础)

学习资料&#xff1a;尚硅谷_爬虫 学习环境: pycharm 一.爬虫基本概念 爬虫定义 > 解释1&#xff1a;通过程序&#xff0c;根据URL进行爬取网页&#xff0c;获取有用信息 > 解释2&#xff1a;使用程序模拟浏览器&#xff0c;向服务器发送请求&#xff0c;获取相应信息…

尚品汇-(五)

商品管理模块开发 下面用到的表&#xff1a; 属性表&#xff1a; 属性值表&#xff1a; 分类一表&#xff1a; 分类二表&#xff1a; 分类三表&#xff1a; 1.1在service 模块下搭建service-product 搭建过程同common-util 添加配置文件application.yml spring:applicatio…

C#基于SkiaSharp实现印章管理(1)

最近对着微软的教程学习SkiaSharp的概念及用法&#xff0c;由于之前使用GDI绘制过坐标系、印章等程序&#xff0c;准备使用SkiaSharp、SKControl控件编写简单的印章设计功能&#xff0c;并能用印章对图片盖章。本文实现创建印章背景、序列化及反序列化印章对象等功能。   VS2…

2-14 基于matlab的GA优化算法优化车间调度问题

基于matlab的GA优化算法优化车间调度问题。n个工作在m个台机器上加工。已知每个工作中工序加工顺序、各工序的加工时间以及每个工件所包含的工序&#xff0c;在满足约束条件的前提下&#xff0c;目的是确定机器上各工件顺序&#xff0c;以保证某项性能指标最优。程序功能说明&a…

视频讲解|【双层模型】分布式光伏储能系统的优化配置方法

1 主要内容 该讲解视频对应的程序链接为【双层模型】分布式光伏储能系统的优化配置方法&#xff0c;模型参考《分布式光伏储能系统的优化配置方法》&#xff0c;分为上下层求解方式&#xff0c;上层采用粒子群算法确定储能的选址和容量方案&#xff0c;以全年购电成本、网络损…

YouTube API接口:一键获取Playlist视频合集信息

核心功能介绍 在视频内容日益繁荣的今天&#xff0c;YouTube作为全球领先的视频分享平台&#xff0c;为内容创作者、品牌商家以及数据分析师提供了丰富的视频资源。其中&#xff0c;Playlist视频合集作为YouTube上的一种特色内容形式&#xff0c;深受用户喜爱。为了更好地满足…

TCP与UDP_三次握手_四次挥手

TCP vs UDP TCP数据 具体可以通过Cisco Packet Tracer工具查看&#xff1a; UDP数据 三次握手、四次挥手 为什么是3/4次&#xff1f;这牵扯到单工、双工通信的问题 TCP建立连接&#xff1a;表白 TCP释放连接&#xff1a;分手 TCP—建立连接—三次握手 解释&#xff1a; 首先&…