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

开发实战|Maven中的依赖传递详解 在Maven中,依赖通过<dependency>标签在项目的pom.xml文件中声明,并且可以通过标签来控制依赖的作用范围。依赖传递是基于依赖树实现的,如果A依赖于B,而B又依赖于C,则A也间接依赖于C。然而,这种依赖传递可能会受到依赖版本冲突、作用范围等因素的影响。本篇就是一个scope后续,主要理解下什么是传递依赖、如何设置、如何避免传递依赖,希望通过以上方法,可以有效地管理和解决 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个问题:

  1. Maven是单继承的,一个项目只能有一个parent项目
  2. 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高级-分模块开发和设计及依赖管理 Maven高级-分模块开发与设计及依赖管理简单示例 阅读详情

相关推荐

Maven依赖中的runtime与provided有什么区别?

在使用Maven进行项目管理时,依赖的管理是一个重要的环节。在这个过程中,理解不同的依赖作用域是至关重要的。特别是runtime和provided这两种作用域,它们在项目构建和运行中的角色和含义各有不同。接下来,我们就来详细聊聊这两者的不同之处,以及它们各自的应用场景!

字节王德发 894

【Maven从入门到实战教程】第六章 Maven依赖传递详解

一、理解依赖传递 二、依赖传递的排除 三、依赖冲突与解决

波哩个波的博客 3162

Maven:传递依赖

Maven:传递依赖

啊Q老师 875

3. maven依赖传递

依赖范围 上一篇博客提到,在pom文件中引用其他依赖时,可以指定依赖的范围 例如,test范围支队测试代码有效,对编译或运行主代码无效 这里maven在编译、运行和测试时,会使用三套不同的classpath:编译classpath、运行classpath、测试classpath。 依赖范围,就是用来控制引入的依赖与这三种classpath之间的关系 。 maven的中依赖范围: compile: 编译依赖范围,若不明确指定scope,默认使用该值。compile范围的依赖,对编译classpath、

lucyLee的博客 3699

Maven(五)-- Maven 依赖配置 、依赖传递 与 依赖范围

因为Maven依赖具有传递性,故,我们在开发的过程中,就不可避免地出现Maven。(1)路径优先:当依赖中出现相同资源时,层级越深,优先级越低,反之则越高。(3)特殊优先:当同级配置了相同资源的不同版本时,后配置的覆盖先配置的。(2)声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖靠后的。:被依赖的资源如果依赖其他资源,则表明当前项目间接依赖其他资源。(2)测试程序范围内有效(src/test目录范围内)。(1)主程序范围有效(src/main目录范围内)。:在当前项目中通过依赖配置建立的依赖关系。

PUYALEI的博客 253

GEO优化内容营销策略:从规划到落地的全流程指南

GEO内容营销是通过地域化内容提升本地搜索排名、增加流量和转化率的策略。核心包括:构建本地用户画像,挖掘需求关键词;策划本地文化融合、案例研究等多样化内容;通过网站、社交媒体、本地KOL等渠道精准分发;优化本地关键词和视觉元素;监测数据并动态调整。案例显示,咖啡馆、工业企业和服装品牌通过本地化短视频、KOL合作及社群运营,显著提升了搜索排名、客流量和销售额。关键原则是内容本地化、精准分发、KOL合作、激励用户生成内容及数据驱动优化,实现高效本地市场渗透。

解锁AI流量新红利!🚀 GEO优化(生成引擎优化)助您掌控AI搜索,让AI成为您的品牌最佳代言人! 1331

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

Maven依赖传递、依赖管理、依赖作用域讲解。

申城异乡人 1146

408——计算机组成原理(持续更新)

小数点前的0代表正数,1代表负数。

qq_55202378的博客 1724

【Gradle】(三)详细聊聊依赖管理:坐标、依赖配置、依赖传递、依赖冲突

本文着重针对 Gradle 的依赖管理展开了全方位且极为详尽的介绍。在此过程中,清晰明确地提及了诸如坐标、依赖的基础概念、依赖配置、依赖传递还有依赖冲突等相关特性。在充分熟知并掌握了这些特性之后,于后续开展的工作当中,就能够更加精确、细致地对依赖进行管理,并且可以妥善、有效地处理由依赖冲突所引发的各种各样的问题。

积木成林,聚沙成塔 3640

惯性导航原理(九)-INS的初始对准-初始姿态确定+双矢量定姿

文章目录INS的初始对准INS初始化静基座/静态粗对准静态粗对准—加速度计调平原理加速度计调平静态粗对准—陀螺罗盘思考初始对准的影响因素双矢量定姿原理静态解析粗对准—双矢量定姿静态解析粗对准(续)其它初始对准方法精对准动对准 INS的初始对准 INS的初始对准为初始化的一部分 INS初始化 初始位置: 给定(INS没有初始位置确定的能力,例如从GPS ) 初始速度: 零(静止状态)或给定 初始姿态: 初始对准(INS有能力自己测资态) 粗对准vs. 精对准 静止状态vs. 运动状态 重要性: 失之毫厘,谬

十八与她的博客 1万+

Bybit面经

这段总结描述了求职者在Bybit面试过程中的经历和相关问题,包括面试内容、求职者向面试官提问的问题以及关于Bybit的信息

郑泽洲的博客 2584

Maven 依赖传递:项目依赖的神奇魔法

在 Java 开发的世界里,Maven 就像是一位贴心的管家,帮我们打理着项目中的各种依赖关系。而其中的依赖传递功能,更是犹如魔法一般,让我们的开发工作变得更加高效和便捷。今天,咱们就来好好聊聊 Maven 的依赖传递,探究一下它到底是什么,又解决了哪些令人头疼的问题。

恩爸编程 1010

PTPX功耗分析实战——从脚本配置到报告解读

本文详细介绍了PTPX功耗分析的全流程,从脚本配置到报告解读,帮助工程师快速掌握芯片设计中的功耗估算技术。文章涵盖了环境搭建、波形文件处理、功耗报告解析等关键环节,并提供了实战经验和优化建议,特别适合需要提升PTPX功耗分析效率的开发者。

weixin_29248313的博客 280

【Maven】(四)图解Maven3依赖的功能特性:依赖范围、依赖传递、依赖冲突

在本篇中,我们了解了依赖的相关功能特性: 依赖范围:不同的`scope`对应不同的classpath。 依赖传递:在特定的依赖范围下,依赖会向上传递。 可选依赖:使用 `optional` 可以禁止依赖向上传递 依赖冲突:引入不同版本的相同构件会发生依赖冲突,Maven自带依赖调解机制 依赖排除:可以手动使用`exclusions`排除依赖构件中的间接依赖

积木成林,聚沙成塔 2860

卡尔曼滤波原理详解及系统模型建立(simulink)

卡尔曼滤波原理详解及系统模型建立(simulink) 卡尔曼滤波器 卡尔曼滤波器是在上个世界五六十年代的时候提出的,到今天已经有六十年左右的时间,但卡尔曼滤波算法不管在控制、制导、导航或者通讯方面对数据的预测能力依然处在一个不可撼动的位置上,但是很多人对于其算法内部的工作原理究竟是怎么运作的依然不理解,所以在工程上很多人都只是把卡尔曼滤波当成是一种“黑箱”预测算法,并不清楚内部原理。但实际上没有任...

weixin_43942325的博客 7万+

模拟一个基站和一个移动台之间的信号传播

同样使用时间序列和上述参数计算出反射径信号的信号强度。根据时间序列和上述参数,计算出直射径信号的信号强度。该信号被视为一个简单的正弦波信号,其频率是2Hz。:时间序列,从0.1秒开始,每隔0.0001秒采样一次,直到12秒。:设置坐标轴范围,横轴范围为0到12秒,纵轴范围为-0.5到0.5。:移动台移动的速度。:移动台距离基站的初始距离。:基站到反射墙的距离。假设基站到反射墙的距离为15米。:绘制直射径信号、反射径信号和合成信号的波形图。:添加标签,标注每条曲线对应的含义。表示反射径信号的颜色为绿色,

Fanjufei的博客 292

Maven - 依赖的生命周期详解

本文由唐叔为大家深入浅出讲解Maven依赖的生命周期,涵盖依赖声明、传递性依赖、依赖范围、依赖调解等核心概念,结合实战案例解析如何高效管理项目依赖关系。无论你是Java开发新手还是资深架构师,这篇文章都能让你对Maven依赖有全新认识!

唐叔学习中... 1698

cartographer运行错误集合

播放bag的时候错误 Check failed: sensor_to_tracking->translation().norm() < 1e-5 The IMU frame must be colocated with the tracking frame. Transforming linear acceleration into the tracking frame will otherwise be imprecise tracking frame不是imu的link 修改lua文件中的.

Studying…… 2032

聊聊Maven中的10个坑

今天这篇文章跟大家总结一下,使用Maven时一些最常见的坑,希望对你会有所帮助。最近经常遇到知识星球中的小伙伴,问我一些关于Maven的问题。说实话,Maven在我们日常开发中,使用的频率非常高。:相同版本号可能对应不同内容,导致生产环境行为不一致。随机出现,因类加载器加载了错误Jar。:JDK 17+项目使用旧版编译器插件。坑10:IDE与命令行行为不一致。2.Maven中最常见的坑。:Tomcat中运行时抛出。:引入A、B两个组件。坑7:多模块构建顺序。

weixin_44066506的博客 899

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Maven 精准控制依赖:排除 JAR 包中的特定内容与子依赖

本文深入解析了Maven依赖管理中精准控制的两种核心方法:使用<exclusion>排除传递性子依赖以解决JAR包冲突,以及使用<exclude>在构建阶段剔除JAR包内部的无用资源文件以实现项目瘦身。文章通过实战案例和避坑指南,帮助开发者高效管理依赖,优化项目结构。

rgv2345678的博客 435

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

漫谈依赖管理工具:从Maven,Gradle到Go

为什么要有依赖管理工具? 谈依赖管理之前,我们先谈谈为什么要有依赖管理工具这东西。 我们学了一种编程语言,然后写了个“Hello World”,然后宣称自己学了一门语言,这时候确实不需要关心依赖问题。 然而,当你要写一个稍微复杂点的应用,那怕就是留言板这样的,需要读写数据库,就需要依赖数据库驱动,就会遇到依赖管理的问题了。 再进一步,你写了一个库,想共享给别人使用,更需要了解依赖管理的问题。 当然...

weixin_33672400的博客 288

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: 如何使用Java获取货币符号?
下一篇: 设计模式——二:里氏替换原则
加班不秃顶
博客等级 码龄7年 1822粉丝 599原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值