聊聊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,然后它会返…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...