Maven中scope(作用范围)详解

news2024/12/26 11:29:10

目录

    • 一、依赖传递
    • 二、依赖范围
    • 三、依赖范围对传递依赖的影响
    • 四、依赖调节
    • 五、可选依赖
    • 六、排除依赖
    • 七、依赖归类
    • 八、依赖管理

一、依赖传递

Maven 依赖传递是 Maven 的核心机制之一,它能够一定程度上简化 Maven 的依赖配置。

如下图所示,项目 A 依赖于项目 B,B 又依赖于项目 C,此时 B 是 A 的直接依赖,C 是 A 的间接依赖。

Maven 的依赖传递机制是指:不管 Maven 项目存在多少间接依赖,POM 中都只需要定义其直接依赖,不必定义任何间接依赖,Maven 会自动读取当前项目各个直接依赖的 POM,将那些必要的间接依赖以传递性依赖的形式引入到当前项目中。Maven 的依赖传递机制能够帮助用户一定程度上简化 POM 的配置。

基于 A、B、C 三者的依赖关系,根据 Maven 的依赖传递机制,我们只需要在项目 A 的 POM 中定义其直接依赖 B,在项目 B 的 POM 中定义其直接依赖 C,Maven 会解析 A 的直接依赖 B的 POM ,将间接依赖 C 以传递性依赖的形式引入到项目 A 中。

通过这种依赖传递关系,可以使依赖关系树迅速增长到一个很大的量级,很有可能会出现依赖重复,依赖冲突等情况,Maven 针对这些情况提供了如下功能进行处理。

  • 依赖范围(Dependency scope)
  • 依赖调解(Dependency mediation)
  • 可选依赖(Optional dependencies)
  • 排除依赖(Excluded dependencies)
  • 依赖管理(Dependency management)

二、依赖范围

首先,我们要知道 Maven 在对项目进行编译、测试和运行时,会分别使用三套不同的 classpath。Maven 项目构建时,在不同阶段引入到 classpath 中的依赖时不同的。

我们可以在 POM 的依赖声明使用 scope 元素来控制依赖与三种 classpath(编译 classpath、测试 classpath、运行 classpath )之间的关系,这就是依赖范围。

下面我们首先要对三种classpath进行了解:

  • 我们使用idea跑项目当中src/main/java目录下的代码实际上就是运行的当前项目target/classes目录下的字节码文件。
  • 我们使用idea跑项目当中src/test/java目录下的代码实际上就是运行的当前项目target/test-classes目录下的字节码文件。
  • 为什么这里要说是war包而不是jar包,因为jar包是可以直接运行的,而war包是需要依赖于tomcat的。

可选配置有 compile、test、provided、runtime、system、import,若不指定则默认 compile。 首先我们要知道classes和test-classes目录是不存jar包的,项目所依赖的jar包直接使用的是本地maven仓库的,依赖范围更为通俗的理解,其实就是给依赖包打标记,例如将 A 依赖包标记为“compile”,Maven 就知道 A 依赖包不仅运行classes目录的代码要用,运行test-classes也要用,打成的war包也要用(打包就是需要把依赖的包也打包到war,这样war就可以不依赖于本地仓库而放到tomcat当中进行运行了)。

  • compile(编译依赖范围):使用此依赖范围的Maven 依赖,对于编译、测试、运行三种classpath 都有效。典型的例子是spring-core,在编译、测试和运行的时候都需要使用该依赖。
  • test(测试依赖范围):只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子是junit,它只有在编译测试代码及运行测试的时候才需要。
  • provided:对于编译和测试classpath有效,但在运行时无效。典型的例子是 servlet-api,,编译和测试项目的时候需要该依赖,假如需要打包成war然后放到tomcat当中运行,由于tomcat已经提供,就不需要Maven重复地引入一遍。所以将 scope 设置为 provided 的依赖不会参与项目的war打包。假如打包为jar,设置与不设置provided并不会影响maven将依赖打包到jar当中

说到provided,这里就要说到<dependency>下的子标签<optional> ,这两者的区别在于:
1、<optional>为true 表示依赖不会传递。例如:x依赖B,B又依赖于A(x->B->A),则A中设置<optional> 为true的依赖不会被传递到x中。假如当前项目某个依赖<optional>为true 并不会影响该依赖在当前项目的打包,他只会影响所依赖当前项目的其他项目打包。
2、<scope>为provided 代表的是该依赖不参与打war包。

在目标容器中已经提供了这个依赖,无需在提供
关于optional的详解:https://blog.csdn.net/weixin_43888891/article/details/130510971

  • runtime(运行时依赖范围): 运行时依赖范围:对于测试和运行class-path有效,但在编译主代码时无效(对编译的classpath无效)。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
  • system(系统依赖范围):需要引用第三方本地jar包的时候使用,案例:https://blog.csdn.net/weixin_43888891/article/details/130611728
  • import(导入依赖范围): 导入依赖范围,该依赖范围只能与 dependencyManagement 元素配合使用,其功能是将目标 pom.xml 文件中 dependencyManagement 的配置导入合并到当前 pom.xml 的 dependencyManagement 中。案例:https://blog.csdn.net/weixin_43888891/article/details/130520345

依赖范围与三种 classpath 的关系一览表,如下所示。

三、依赖范围对传递依赖的影响

项目 A 依赖于项目 B,B 又依赖于项目 C,此时我们可以将 A 对于 B 的依赖称之为第一直接依赖,B 对于 C 的依赖称之为第二直接依赖。

B 是 A 的直接依赖,C 是 A 的间接依赖,根据 Maven 的依赖传递机制,间接依赖 C 会以传递性依赖的形式引入到 A 中,但这种引入并不是无条件的,它会受到依赖范围的影响。

传递性依赖的依赖范围受第一直接依赖和第二直接依赖的范围影响,如下表所示。

注:上表中,左边第一列表示第一直接依赖的依赖范围,上边第一行表示第二直接依赖的依赖范围。交叉部分的单元格的取值为传递性依赖的依赖范围,若交叉单元格取值为“-”,则表示该传递性依赖不能被传递。

通过上表,可以总结出以下规律:

  • 当第二直接依赖的范围是 compile 时,传递性依赖的范围与第一直接依赖的范围一致;
  • 当第二直接依赖的范围是 test 时,传递性依赖不会被传递;
  • 当第二直接依赖的范围是 provided 时,只传递第一直接依赖的范围也为 provided 的依赖,且传递性依赖的范围也为 provided;
  • 当第二直接依赖的范围是 runtime 时,传递性依赖的范围与第一直接依赖的范围一致,但 compile 例外,此时传递性依赖的范围为 runtime。

四、依赖调节

Maven 的依赖传递机制可以简化依赖的声明,用户只需要关心项目的直接依赖,而不必关心这些直接依赖会引入哪些间接依赖。但当一个间接依赖存在多条引入路径时,为了避免出现依赖重复的问题,Maven 通过依赖调节来确定间接依赖的引入路径。

依赖调节遵循以下两条原则:

  • 引入路径短者优先:
  • 先声明者优先

以上两条原则,优先使用第一条原则解决,第一条原则无法解决,再使用第二条原则解决。

引入路径短者优先

引入路径短者优先,顾名思义,当一个间接依赖存在多条引入路径时,引入路径短的会被解析使用。

例如,A 存在这样的依赖关系:

  • A->B->C->D(1.0)
  • A->X->D(2.0)

D 是 A 的间接依赖,但两条引入路径上有两个不同的版本,很显然不能同时引入,否则造成重复依赖的问题。根据 Maven 依赖调节的第一个原则:引入路径短者优先,D(1.0)的路径长度为 3,D(2.0)的路径长度为 2,因此间接依赖 D(2.0)将从 A->X->D(2.0) 路径引入到 A 中。

先声明者优先

先声明者优先,顾名思义,在引入路径长度相同的前提下,POM 文件中依赖声明的顺序决定了间接依赖会不会被解析使用,顺序靠前的优先使用。

例如,A 存在以下依赖关系:

  • A->B->D(1.0)
  • A->X->D(2.0)

D 是 A 的间接依赖,其两条引入路径的长度都是 2,此时 Maven 依赖调节的第一原则已经无法解决,需要使用第二原则:先声明者优先。

A 的 POM 文件中配置如下。

<dependencies>
    ...      
    <dependency>
        ...
        <artifactId>B</artifactId>       
        ...
    </dependency>
    ...
    <dependency>
        ...
        <artifactId>X</artifactId>
        ...
    </dependency>
    ...
</dependencies>

有以上配置可以看出,由于 B 的依赖声明比 X 靠前,所以间接依赖 D(1.0)将从 A->B->D(1.0) 路径引入到 A 中。

五、可选依赖

可选依赖就是指的optional标签,关于optional的详解:https://blog.csdn.net/weixin_43888891/article/details/130510971

六、排除依赖

传递性依赖可以帮助我们简化项目依赖的管理,但是同时也会带来其他的不必要的风险,例如:会隐式地引入一些依赖,这些依赖可能并不是我们希望引入的,或者这些隐式引入的依赖是 SNAPSHOT 版本的依赖。依赖的不稳定导致了我们项目的不稳定。

在我们的项目中,spring-boot-starter-test 依赖中排除了 junit-vintage-engine 依赖是由于我们使用的 springboot 版本是 2.2.6-RELEASE,对应的 Junit 版本是 5.x,但 junit-vintage-engine 依赖中包含了 4.x 版本的 Junit,此时我们就可以将该依赖排除。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

关于 exclusions 元素及排除依赖说明如下:

  • 排除依赖是控制当前项目是否使用其直接依赖传递下来的接间依赖;
  • exclusions 元素下可以包含若干个 exclusion 子元素,用于排除若干个间接依赖;
  • exclusion 元素用来设置具体排除的间接依赖,该元素包含两个子元素:groupId 和 artifactId,用来确定需要排除的间接依赖的坐标信息;
  • exclusion 元素中只需要设置 groupId 和 artifactId 就可以确定需要排除的依赖,无需指定版本 version。

七、依赖归类

在我们实际的开发过程中,我们可能会需要整合很多第三方框架,在整合这些框架的时候,往往需要在 pom.xml 里面添加多个依赖来完成整合。而这些依赖往往是需要保持相同版本的,在升级框架的时候,都是要统一升级到一个相同的版本。

如下图,我们可以看到,在引入 dubbo 框架的时候,我们需要引入两个相关的依赖,而且版本号是相同的,这个时候,我们就可以把对应的版本号提取出来,放到 properties 标签里面,作为一个全局参数来使用。类似于 Java 语言中抽象的思想。

这时候,我们可以看到,如果在将来的某一天我们需要升级升级 dubbo 框架对应的版本,只需要修改 properties 中的版本号,就能将所有依赖的版本一起升级。

八、依赖管理

依赖管理就是指的dependencyManagement标签,直接看这一篇文章即可:https://blog.csdn.net/weixin_43888891/article/details/130520345

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

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

相关文章

黄牛为什么能抢走“五月天”的门票?

目录 “史上最难抢票”的五月天演唱会 黄牛为什么能抢到票 黄牛抢票带来哪些坏影响 售票平台为什么挡不住黄牛&#xff1f; 管理上如何有效防控黄牛 技术上如何有效防黄牛 相关技术产品推荐 随着文娱活动的复苏&#xff0c;大量黄牛“卷土袭来”。顶象防御云业务安全情报…

【音视频处理】MP4、FLV、HLS适用范围,在线视频播放哪个更好

大家好&#xff0c;欢迎来到停止重构的频道。 我们之前讨论过直播协议&#xff0c;本期我们讨论在线点播的视频格式。 也就是网络视频文件、短视频常用的格式 如MP4、FLV、HLS等。 我们将详细讨论在线点播场景下&#xff0c;这些视频格式的优劣以及原因。 我们按这样的顺序…

分享几个冷门但实用的网站!

今天给大家推荐几个冷门但实用的网站&#xff0c;免费又好用对于打工人来讲十分友好。 Img Cleaner https://imgcleaner.com/ 一个免费的AI智能图片去水印网站&#xff0c;不用注册登录就可以使用&#xff0c;而且操作也比较简单&#xff0c;上传图片之后调整画笔大小&#xf…

小黑子—Java从入门到入土过程:第十章 - 多线程

Java零基础入门10.0 Java系列第十章- 多线程1. 初识多线程2. 并发和并行3. 多线程的实现方式3.1 一&#xff1a;继承Thread类方式实现3.2 二&#xff1a;实现Runnable接口的方式实现3.3 三&#xff1a;利用Callable接口和Future接口方式实现 4. 多线程中常见的成员方法4.1 线程…

❤ Manifest version 2 is deprecated, and support will be removed in 2023. See..

❤谷歌插件开发遇到的问题 开发谷歌插件提示&#xff1a; ❤js 开发谷歌插件提示 提示 Manifest version 2 is deprecated, and support will be removed in 2023. See… 当导入到chrome&#xff0c;提示如下错误&#xff1a; Manifest version 2 is deprecated, and suppo…

物联网:智慧城市还要做的事情

摘要&#xff1a;本文简介关于智慧城市&#xff0c;还有哪些需要做的事情。 1.传统城市需要向智慧城市转型 传统的城市中心已被证明不足以满足社会当前和未来的各种需求&#xff0c;这增加了应用智慧城市理念的需求。智慧城市可以对健康、交通、休闲和工业等多个领域产生重大…

VLC可见光通信:2、高速LED驱动电路

背景 在VLC可见光通信中,需要高速的控制LED的通断,因此需要高速LED驱动电路。 文中出现的低压是指24V电压以下,中压是指24V~60V电压,高压是指60V ~ 160V。 低速是指500KHZ以下,高速是指2MHZ。 小功率是指20W以下,大功率指20W~100W。 低压小功率LED低速&高速:20W、…

你是时候拥抱chatgpt了

随着chatgpt热度不断上升&#xff0c;chatgpt已经广泛应用到各个行业了&#xff0c;很多人都感觉自己地位受到威胁&#xff0c;有人预测chatgpt会取代80%程序员的工作&#xff0c;我也用了chatgpt有几个月了&#xff0c;不得不说是真的牛逼。我甚至用它写了一个python的聊天脚本…

MapReduce计算广州2022年每月最高温度

目录 数据集 1.查询地区编号 2.数据集的下载 编写MapReduce程序输入格式 输出格式 Mapper类 确定参数 代码 Reducer类 思路 代码 Runner类 运行结果 数据集 1.查询地区编号 NCDC是美国国家气象数据中心的缩写&#xff0c;是一个负责收集、存储和分发全球气象和气…

C#中将32位二进制转换为float【Real】十进制类型

已知一个32位二进制字符串&#xff0c;转换为float【Real】十进制。 参考本人一篇博客 float数转二进制 C#关于32位浮点数Float&#xff08;Real&#xff09;一步步按位Bit进行解析_real32位浮点数_斯内科的博客-CSDN博客 现在是32位二进制转化为十进制浮点数&#xff0c;C#有…

电动汽车入网技术(V2G)调度优化(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 近年来我国电动汽车行业飞速发展&#xff0c;其中电动汽车入网技术&#xff08;vehicle-to-grid&#xff0c;V2G&#xff09;在…

RapidScada Linux安装教程

官方安装步骤&#xff1a;在 Linux上安装 - Rapid SCADA,安装过程中遇到一些坑&#xff0c;记录详细步骤。 官方推荐的Ubuntu&#xff0c;未测试Centos 1. 安装ASP.Net运行环境&#xff08;Runtime&#xff09; 下载地址&#xff1a;下载 .NET 6.0 (Linux、macOS 和 Windows)&a…

selenium还能这么玩:连接已经存在的浏览器

测试和爬虫对selenium并不会陌生&#xff0c;现有的教程已经非常多。但是因为 selenium 封装的方法比较底层&#xff0c;所以灵活性非常高&#xff0c;我们可以基于这种灵活性来实现非常丰富的定制功能。 这篇文章介绍一个操作&#xff0c;可以让 selenium 连接我们手动打开的…

AI绘画-Midjourney基础2-超强二次元风格模型 niji 5

niji 模型是 mj 的一种模型,可以生成二次元风格的图片。 在控制台输入 /settings 指令,进入设置页面。 选择第二行的 Niji version 5 模型,就可以创作二次元风格的图片了! 一、expressive 风格 expressive 风格是 niji 5 模型的默认风格。 Step into the world :: of a …

14个最佳创业企业WordPress主题

要创建免费网站&#xff1f;从易服客建站平台免费开始 500M免费空间&#xff0c;可升级为20GB电子商务网站 创建免费网站 您网站的设计使您能够展示产品的独特卖点。通过正确的主题&#xff0c;您将能够解释为什么客户应该选择您的品牌而不是其他品牌。 在本文中&#xff0…

信息(文档)和配置管理

信息&#xff08;文档&#xff09; 配置管理 小改动增加Y的值&#xff0c;大改动增加X的值 配置控制

jRebel实现热部署以及云热部署

idea使用jRebel教程很多&#xff0c;不再累述 服务器部署jRebel 1.下载激活工具(github&#xff0c;别忘了加速)&#xff1a;下载链接 因为是linux&#xff0c;固下载下方资源 放进服务器执行下方命令运行&#xff0c;port就是端口号&#xff0c;看着改&#xff0c;我用的888…

什么是GHZ?炫云到底是怎么收费的?

作为一家云渲染“老牌”服务商&#xff0c;炫云的行业资历无疑是悠久的。在广大用户的支持与认可下&#xff0c;炫云砥砺前行迎来蓬勃发展。注册用户体量的剧增&#xff0c;为炫云带来了更多新面孔。在客服汇总的新用户常见问题里&#xff0c;有关“GHZ”与“收费”的字眼出现频…

Hyperf使用WebSocket 服务

1.安装服务 composer require hyperf/websocket-server2.配置 Server 修改 config/autoload/server.php&#xff0c;增加以下配置。 <?phpdeclare(strict_types1); /*** This file is part of Hyperf.** link https://www.hyperf.io* document https://hyperf.wiki*…

ChatGpt使用、小白上手指南,整理5个ChatGpt学习文库和平台

ChatGpt目前很火&#xff0c;话题度很高&#xff0c;关于它的账号售卖、视频课程网上遍地都是&#xff0c;尝试没有窍门&#xff0c;学习付费太高&#xff0c;一不小心就会被割韭菜。 闲暇之余也从网上搜集整理了5个平台&#xff0c;里面系统的介绍了有关ChatGpt的应用和相关&…