聊聊Maven的依赖传递、依赖管理、依赖作用域
1. 依赖传递
在Maven中,依赖是会传递的,假如在业务项目中引入了spring-boot-starter-web
依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.4</version>
</dependency>
那么业务项目不仅直接引入了spring-boot-starter-web
依赖,还间接引入了spring-boot-starter-web
的依赖项:
spring-boot-starter
、spring-boot-starter-json
、spring-boot-starter-tomcat
、spring-web
、spring-webmvc
。
Maven依赖关系如下图所示:
外部库如下图所示:
其中,业务项目对spring-boot-starter-web
的依赖称为直接依赖,对spring-boot-starter-web
的依赖项:
spring-boot-starter
、spring-boot-starter-json
、spring-boot-starter-tomcat
、spring-web
、spring-webmvc
的依赖称为间接依赖。
2. 依赖管理
dependencyManagement元素主要用来统一管理依赖项的版本号。
假如父项目的pom文件中声明了如下依赖:
<dependencyManagement><dependencies><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version></dependency></dependencies>
</dependencyManagement>
那么子项目在添加该依赖时,可以不指定版本号:
<dependencies><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId></dependency>
</dependencies>
Maven会自动找到父项目中声明的该依赖项的版本号,如下图所示:
这样的优点是可以统一在父项目中管理依赖项的版本号,如果需要升级版本,只需改动父项目一个地方即可,子项目不用改动。
说明:
1)dependencyManagement只是声明依赖项,并没引入依赖项,子项目仍需显式引入,不过可以不指定版本号
2)如果子项目不想使用继承的父项目中的版本号,在子项目中指定版本号即可
3. 依赖作用域
在Maven中,可以使用scope
来指定当前依赖项的作用域,常见的值有:compile、provided、runtime、test、import等,如下所示:
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope>
</dependency>
3.1 compile
compile是默认的作用域,如果引入依赖时,没有明确指定作用域,则依赖作用域为compile。
作用域为compile的依赖,在编译、测试和运行时都是可用的,并且会参与项目的打包过程,该依赖会传递给依赖该模块的其他模块。
3.2 provided
作用域为provided的依赖,在编译和测试时是可用的,在运行时是不可用的,不会参与项目的打包过程,也不会传递给其他模块。
比如lombok依赖会在编译时生成相应的get、set等方法,在运行时就不需要这个依赖了,因此常常被指定为provided:
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version><scope>provided</scope>
</dependency>
因为被指定为provided,项目打包时是不包含lombok依赖项的,如下图所示:
如果将上面的代码<scope>provided</scope>
删除的话,运行时是下图这样的:
以上验证需将项目打包方式改为war,打包后查看WEB-INF/lib目录
3.3 runtime
作用域为runtime的依赖,在测试和运行时是可用的,在编译时是不可用的,会参与项目的打包过程,也会传递给依赖该模块的
其他模块。
说明:
作用域为runtime的依赖中的类,在项目代码里不能直接用,用了无法通过编译(这里指的是在src/main/java下使用)。
以mysql-connector-java为例,假如引入依赖时是下面这样的:
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency>
下面的示例代码是可以编译通过的:
如果将作用域修改为runtime,上面的示例代码无法通过编译:
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version><scope>runtime</scope>
</dependency>
3.4 test
作用域为test的依赖,只在测试时可用(包括测试代码的编译、执行),不会参与项目的打包过程,也不会传递给其他模块。
常见的有junit、mockito等:
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
</dependency>
因为被指定为test,项目打包时是不包含junit依赖项的,如下图所示:
如果将上面的代码<scope>test</scope>
删除的话,运行时是下图这样的:
以上验证需将项目打包方式改为war,打包后查看WEB-INF/lib目录
说明:
作用域为test的依赖中的类或者注解只能在src/test/java下才可以使用,在src/main/java下无法使用,如junit包下的@Test
注解和org.junit.Assert
断言类。
3.5 import
每个项目,一般都会继承自一个父项目,在实际的工作中,这个父项目一般都是公司架构组提供的带有公司特色的一个基础项目,
当然也可以是spring boot官方的项目。
以spring boot官方的项目为例:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.4</version>
</parent>
这个父项目中,会使用dependencyManagement
标签对依赖项的版本统一管理,子项目中,可以按需引入父项目
dependencyManagement
中定义的依赖,但可以不指定版本号(版本号会自动继承父项目中定义的版本号)。
但是存在以下2个问题:
- Maven是单继承的,一个项目只能有一个parent项目
- parent项目dependencyManagement中的依赖项会越来越多,不好管理
依赖作用域import的出现就是为了解决以上问题,它可以通过非继承的方式批量引入另一个依赖项中
dependencyManagement元素中定义的依赖项,如下所示:
<dependencyManagement><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-bom</artifactId><version>${spring-session-bom.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
说明:<scope>import</scope>
只能用在dependencyManagement下type为pom的dependency中。
以上代码等价于添加了以下6个依赖项:
可以看出,使用<scope>import</scope>
可以模块化的管理依赖项,提高复用性,pom文件也更加简洁。
3.6 区别
综上所述,各个依赖作用域的区别如下表所示:
scope取值 | 编译时可用 | 测试时可用 | 运行时可用 | 是否参与打包 | 依赖传递 |
---|---|---|---|---|---|
compile | √ | √ | √ | √ | √ |
provided | √ | √ | × | × | × |
runtime | × | √ | √ | √ | √ |
test | × | √ | × | × | × |
4. 影响依赖传递的因素
4.1 依赖作用域(scope)
依赖作用域会影响依赖传递,从上表可以看出,如果scope为provided或者test,该依赖不会传递,只有scope为compile或者runtime,
该依赖才会传递。
4.2 可选依赖(optional)
通过dependency标签引入依赖时,可以通过<optional>
指定该依赖是不是可选的,默认值为false:
<dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId><version>3.2.3</version><optional>true</optional>
</dependency>
如果<optional>
值为true,那么这个依赖不会传递。
相关文章:

聊聊Maven的依赖传递、依赖管理、依赖作用域
1. 依赖传递 在Maven中,依赖是会传递的,假如在业务项目中引入了spring-boot-starter-web依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>…...

centos6/7 SOCKS5 堆溢出漏洞修复(RPM方式)curl 8.4 CVE-2023-38545 CVE-2023-38546
引用 https://darkdark.top/update-curl.html centos6 rpm 升级包下载:https://download.csdn.net/download/sinat_24092079/88425840 yum update libcurl-8.4.0-1.el6.1.x86_64.rpm curl-8.4.0-1.el6.1.x86_64.rpmcentos7 rpm 升级包下载:https://down…...

C#,数值计算——数据建模Proposal的计算方法与源程序
1 文本格式 using System; namespace Legalsoft.Truffer { public class Proposal { public Normaldev gau { get; set; } null; private double logstep { get; set; } public Proposal(int ranseed, double lstep) { this.gau…...

如何使用命令生成动态链接库.dll文件(保姆级教学)
如何使用命令生成动态链接库.dll文件 /*** file 如何使用命令生成动态链接库.dll文件* author jUicE_g2R(qq:3406291309)* * brief 教学演示* tool visual studio2022(2019也适用)* * copyright 2023.10* COPYR…...

Qt之模块介绍
Qt提供了很多功能模块,我们需要知道的是这些模块有些加入了标准库,有一些并没有加入到标准库。至于为什么没有加入到标准库通过chatgpt得到的答案如下: Qt 是一个强大的跨平台 C 框架,它包括了很多核心模块和功能,以支…...

Socks5代理和代理IP
在数字时代,网络工程师必须不断掌握新技术,以解决跨界电商、爬虫数据采集、出海业务扩展、网络安全保护以及游戏性能优化等各种技术挑战。本文将深入探讨Socks5代理和代理IP技术,它们在各个领域中的应用,如何为网络工程师提供了强…...

计算机指令、机器码
目录 背景 在软硬件接口中,CPU 帮我们做了什么事? 从编译到汇编,代码怎么变成机器码? 解析指令和机器码 总结延伸 背景 上大学的时候,我们系里教 C 语言程序设计的老师说,他们当年学写程序的时候&…...

MyLife - Docker安装Consul
Docker安装Consul 个人觉得像consul之类的基础设施在线上环境直接物理机安装使用可能会好些。但是在开发测试环境用docker容器还是比较方便的。这里学习下docker安装consul使用。 1. Consul 镜像库地址 Consul 镜像库地址:https://hub.docker.com/r/hashicorp/consu…...

Leetcode刷题笔记--Hot61-70
1--课程表(207) 主要思路: 用 in 记录每一门课程剩余的先修课程个数,当剩余先修课程个数为0时,将该课程加入到队列q中。 每修队列q中的课程,以该课程作为先修课程的所有课程,其剩余先修课程个数…...

python特别篇—github基本操作手册
一、开始使用 1.1 “Hello world” 1.1.1 github介绍 GitHub是一个基于Git版本控制系统的代码托管平台。它提供了一个在线的代码仓库,使开发者可以将自己的代码存储在云端,并与其他开发者进行协作。GitHub不仅仅是一个代码托管平台,还提供了…...

tiktok直播websocket序列化与反序列化
系列文章目录 websocket训练地址:https://www.qiulianmao.com,正在搭建中 基础-websocket逆向基础-http拦截基础-websocket拦截基础-base64编码与解码基础-protobuf序列化与反序列化视频号直播弹幕采集tiktok protobuf序列化与反序列化实战一:Http轮询更新中tikto...

微信picker弹出之后 , 背景变成灰色是怎么做的
微信小程序在弹出picker组件时,会将页面背景变为半透明的灰色,这是通过设置一个全屏的蒙层来实现的。 具体实现方法如下: 在WXML文件中,添加一个view元素作为蒙层,并设置其样式和属性: <view class&q…...

通用考勤后台管理系统
考勤后台系统,包括待办事项、人员管理、任务中心、任务详情、我的任务、客户管理、考勤功能几大功能,本后台系统以考勤打卡为主要功能,采用分屏布局的方式,简洁大方,使用方便...

LeetCode75——Day5
文章目录 一、题目二、题解 一、题目 345. Reverse Vowels of a String Given a string s, reverse only all the vowels in the string and return it. The vowels are ‘a’, ‘e’, ‘i’, ‘o’, and ‘u’, and they can appear in both lower and upper cases, more t…...

面向C++模块的开源 IFC SDK
早在 VS2019 v16.10 版本的时候,我们就官宣了对 C 模块(以及几乎所有其他 C 20 特性)的全面支持,包括 MSVC 编译器工具集,静态分析,智能感知和调试器等,而实现模块需要将 C 代码实现为一种内部的临时表示形式。 今天&…...

Docker开启远程访问+idea配置docker+dockerfile发布java项目
一、docker开启远程访问 1.编辑docker服务文件 vim /usr/lib/systemd/system/docker.servicedocker.service原文件如下: [Unit] DescriptionDocker Application Container Engine Documentationhttps://docs.docker.com Afternetwork-online.target docker.socke…...

基于nodejs+vue教学辅助管理系统
学生;首页、个人中心、本课程设计了线上教学辅助系统 ,学生可以此系统实现在线学习,作业提交管理、作业成绩管理。随着社会的快速发展,计算机的影响是全面且深入的。教师:首页、个人中心、课程信息管理、教学资料管理、作业信息管…...

Qt 子线程中无限递归的信号槽导致主线程槽失效的原因和解决办法
Qt 子线程中无限递归的信号槽导致主线程槽失效的原因和解决办法 问题描述 在一个 Qt6.5.3 的项目中,有一个 ImageProcessor 类负责在子线程中进行图像处理,并有一个 MainWindow 类在主线程中进行界面更新。虽然 ImageProcessor::processingDone 信号被…...

实施 DevSecOps 最佳实践
DevSecOps 是一个框架,它将开发 (Dev)、IT 运营 (Ops) 和安全 (Sec) 流程的实践融合到一个简化的流程中。使用这种方法,DevSecOps 团队能够确保将安全性集成到软件开发生命周期中,确保以“安全第一”的心态构建、部署和维护软件。在本教程中&…...

第56节——redux-toolkit中的createAction——了解
一、概念 createAction 是一个用于创建 Redux action creator 的函数,它可以让你更快地编写 Redux 相关的代码,并且更加易于阅读和维护。 二、简单示例 使用 createAction,你只需要传入一个字符串类型的 action type,然后它会返…...

【数据结构】排序--选择排序(堆排序)
目录 一 堆排序 二 直接选择排序 一 堆排序 堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是 通过堆来进行选择数据。 需要注意的是排升序要建大堆,排降序建小堆。 直接选择排…...

C# 图解教程 第5版 —— 第2章 C# 和 .NET Core
文章目录 2.1 .NET 框架的背景2.2 为什么选择 .NET Core(和 Xamarin)2.3 .NET Core 的目标2.4 多平台支持2.5 快速发展和升级2.6 程序占用空间小、部署简单、版本问题少2.7 开源社区支持(*)2.8 改进的应用程序性能2.9 全新的开始&…...

数据结构 | Huffman TreeCode
构造参考: 赫夫曼树_关于huffman树,权值相同-CSDN博客 编码参考: 【数据结构与算法】-哈夫曼树(Huffman Tree)与哈夫曼编码_数据结构哈夫曼树编码-CSDN博客...

mysql拼接字符串函数
在MySQL中,可以使用CONCAT()函数来拼接字符串。CONCAT()函数接受一个或多个字符串作为参数,并将它们连接在一起。以下是CONCAT()函数的使用示例: 拼接两个字符串: SELECT CONCAT(Hello, , World); -- 输出: Hello World 拼接列中…...

python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域 目录 python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域 1、先来看个问题吧: 2、引用 VS 拷贝: 3、增强赋值以及共享引用:...

《动手学深度学习 Pytorch版》 8.6 循环神经网络的简洁实现
import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2lbatch_size, num_steps 32, 35 train_iter, vocab d2l.load_data_time_machine(batch_size, num_steps)8.6.1 定义模型 num_hiddens 256 rnn_layer nn.RNN(len(voca…...

leetcode做题笔记173. 二叉搜索树迭代器
实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器: BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在…...

RPA流程自动化的优势和好处
随着科技的发展,RPA机器人自动化过程已成为企业提高效率和降低人力成本的一种有效手段。RPA机器人可以模拟和执行人类操作,通过自动执行重复性和繁琐的任务,让员工能够将更多时间和精力投入到更有价值的工作中。 RPA(Robotic Process Automa…...

搭建 Hadoop 生态集群大数据监控告警平台
目录 一、部署 prometheus 环境 1.1 下载安装包 1.2 解压安装 1.3 修改配置文件 1.3.1 hadoop-env.sh 1.3.2 prometheus_config.yml 1.3.3 zkServer.sh 1.3.4 prometheus_zookeeper.yaml 1.3.5 alertmanager.yml 1.3.6 prometheus.yml 1.3.7 config.yml 1.3.8 t…...

课题学习(七)----粘滑运动的动态算法
一、 粘滑运动的动态算法 在实际钻井过程中,钻柱会出现扭振和粘滑现象(粘滑运动–B站视频连接),但并不总是呈现均匀旋转。如下图所示,提取一段地下数据时,转盘转速保持在100 r/min,钻头转速在0-…...