Maven依赖管理总结 #CSDN博文精选# #依赖管理# #IT# #第三方集成#

2023-11-02

大家好,小C将继续与你们见面,带来精选的CSDN博文~

在这里,你将收获:

  • 将系统化学习理论运用于实践,系统学习IT技术
  • 学习内容涵盖数据库、软件测试、主流框架、领域驱动设计和第三方生态等,离全栈工程师更近一步
  • 精心整理的CSDN技术大咖博文,假期学习实现弯道超车

春节假期过后,已经正式开始工作了~专栏《全栈工程师养成记》也进入了尾声,今天就是小C陪伴你们学习这个专栏的最后一天了!

本文来自CSDN博主@Super-小龙

 

前言

Maven作为当下最流行的项目管理工具,其中核心功能就是依赖管理。本文主要总结Maven依赖管理中依赖范围和依赖冲突的解决。

依赖范围

依赖是maven项目引用的资源架包,依赖范围就是这些资源架包在maven项目中的作用范围,反过来说,maven项目通过依赖范围来控制何时引用资源架包。之前有介绍maven的默认生命周期,(compile,test,package,install,deploy)。maven的依赖范围用scope关键字表示,恰好也是五种,虽然不是和生命周期完整对应的,但是基于生命周期划分的。
在这里插入图片描述
通过下表可以知道依赖范围表示的作用域。

依赖范围 对于编译执行环境有效 对于测试执行环境有效 对于运行时执行环境有效 例 子
compile spring-core
test × × junit
provided × servlet-api
runtime × JDBC驱动
system × 本地的,Maven仓库之外的类库

compile:依赖范围默认值是compile,这是最常用的,如果maven项目中引入一个依赖,没有添加scope依赖范围,那么默认的就是compile,表示maven项目在编译,测试,运行阶段都需要引用该依赖。
test:表示该依赖包只和测试相关,测试代码的编译和运行会引用该依赖。
provided:表示maven项目只在编译和测试时引用该依赖,如果将项目打包运行时,则不会引入该依赖,如servlet-api,这是web项目常用的架包,在项目编译和测试时都需要用到该架包,如果项目需要运行,则需要将项目部署到tomcat或其他web服务器上,但是tomcat中自带了servlet-api,如果maven项目中引入了servlet-api,那么会和tomcat中的servlet-api产生冲突,所以可以使用provided限定servlet-api,让maven项目在打包时不再引入servlet-api.

runtime和system是不常用的。runtime表示在测试和运行阶段需要引入该依赖,在编译阶段不引入该依赖,如JDBC的驱动包,因为JDBC驱动是通过反射机制加载的,所以不参与项目编译过程。system的作用域和provided类似,表示引用仓库之外的依赖,需要通过systemPath指定本地依赖的路径,除了特殊情况基本不使用。

传递依赖冲突的解决

先了解一下传递依赖以及什么情况下会产生冲突。
传递依赖,如果项目A需要引入依赖包B,依赖包B又引入了依赖包C,那么B是A的直接依赖,C是A的传递依赖。如果项目A还需要引入依赖包D,依赖包D也引用了依赖包C,当依赖包B引用的C和依赖包D引用的C版本不同时,则发生了依赖冲突。
通过实例说明:一下是Spring的架构图(4.X版本的官方参考文档,5.X版本的没找到,地址:https://docs.spring.io/spring/docs/4.3.21.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#overview-modules)
在这里插入图片描述

现在项目中使用到AOP和Messaging两个模块,在pom.xml文件中引入两个模块的架包坐标信息。

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.3.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-messaging</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>

由下面的依赖层次结构图可知这两个模块都依赖于spring-core和spring-beans核心架包,这里只看spring-beans架包。
在这里插入图片描述
由上图可知,项目(A)依赖spring-aop(B)和spring-messaging(D)两个架包,而spring-aop(B)又依赖于spring-beans ( C),spring-messaging(D)也依赖于spring-banes( C),但是两个依赖的C版本不一样,spring-messaging引入的spring-beans:4.1.7.RELEASE后面括号中提示因为和4.3.7版本冲突而忽略了,也就是说spring-beans:4.1.7并没有被项目(A)引用。
在这里插入图片描述
查看此时项目中引用的maven依赖,spring-beans的版本是4.3.7.
以上情况是因为maven具有自调节的maven传递依赖的冲突解决。
总结一下maven传递依赖冲突解决方案:

1.Maven自调节原则

1.1 第一声明优先原则

在pom.xml文件中引入两个模块 AOP 和 Messaging 的架包坐标信息,先声明的是AOP模块,当AOP和Messaging的依赖包发生冲突时,项目只会引入AOP模块底下的冲突依赖包,Messaging的冲突依赖包则会被排除。
将AOP和Messaging的声明信息调换一下位置:

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-messaging</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.3.7.RELEASE</version>
		</dependency>

在pom.xml文件中声明Messaging模块,或者先加入spring-messaging架包,那么项目中会引入spring-messaging下的冲突架包。
在这里插入图片描述

1.2 路径近者优先原则

这个就比较好理解了,就是直接依赖优先于传递依赖,当然会存在多层依赖,当多层依赖发生冲突时,maven的依赖管理会优先引入依赖层级最少的冲突依赖。如:
在这里插入图片描述
项目直接引入spring-aop(4.3.7版本),项目引入的spring-messaging架包的依赖 spring-context,spring-context又依赖于spring-aop(4.1.7版本),那么项目肯定会优先引入AOP的4.3.7版本,因为这个依赖路径最短。

因为Maven具有自调节依赖冲突解决原则,所以项目中不会发生依赖冲突的错误,但是如果想要自定义选择依赖包的版本,可以用以下方法。

2.排除依赖

排除依赖顾名思义就是将不需要的依赖排除,这也是依赖冲突的一种解决方案。

如,项目A依赖于B,B依赖于C,项目A依赖于D,D依赖于C,如果在项目A的pom.xml中先定义B,根据maven自调节的第一声明优先原则,那么D依赖的C就会被默认排除。此时,如果使用关键字exclusion在B中排除C,那么C自然不会再发生冲突了,因为B依赖的C被排除了,项目A会引入D依赖的C。

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-messaging</artifactId>
			<version>4.1.7.RELEASE</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-beans</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.3.7.RELEASE</version>
		</dependency>

在这里插入图片描述
spring-messaging中使用exclusion关键字排除spring-beans依赖包,可以看到依赖层级中,spring-messaging依赖中没有spring-beans,所以项目中引入的是spring-aop底下的spring-beans(4.3.7版本)。这就是排除依赖的使用。

3.版本锁定(重点)

所谓版本锁定就是指定依赖包的版本,这种依赖冲突的解决方案是目前实际项目中使用的最多的。
版本锁定使用< dependencyManagement >节点

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-core</artifactId>
				<version>4.3.2.RELEASE</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-aop</artifactId>
				<version>4.3.2.RELEASE</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-context</artifactId>
				<version>4.3.2.RELEASE</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-messaging</artifactId>
				<version>4.3.2.RELEASE</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-beans</artifactId>
				<version>4.3.2.RELEASE</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-expression</artifactId>
				<version>4.3.2.RELEASE</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-messaging</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.3.7.RELEASE</version>	
		</dependency>
	</dependencies>

需要说明的是< dependencyManagement >节点仅仅起指定依赖包版本的作用。依赖包的引入仍然是由以下内容确定,如果pom.xml引入依赖包的节点设置了< version >,那么项目中则会引入该版本,如果在< dependencyManagement >节点指定了依赖包的版本,引入依赖包的节点可以不用设置版本。

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-messaging</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.3.7.RELEASE</version>	
		</dependency>
	</dependencies>

如下图所示 :spring-messaging和spring-aop版本分别是4.1.7和4.3.7,而其他的版本都指定为4.3.2版本。如果将依赖包的坐标信息中的< version >去掉,那么spring-messaging和spring-aop的版本也会变为< dependencyManagement >设定的4.3.2版本。
在这里插入图片描述
为了项目版本依赖管理的统一和方便升级,版本信息通常使用OGNL表达式表示,如下:

	<properties>
		<spring-version>4.3.2.RELEASE</spring-version>
	</properties>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-core</artifactId>
				<version>${spring-version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-aop</artifactId>
				<version>${spring-version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-context</artifactId>
				<version>${spring-version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-messaging</artifactId>
				<version>${spring-version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-beans</artifactId>
				<version>${spring-version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-expression</artifactId>
				<version>${spring-version}</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-messaging</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
		</dependency>
	</dependencies>

spring-version是一个自定义的常量名,可以设定值为依赖包的版本,然后在
< dependencyManagement >中引用该值,如果项目需要升级依赖包的版本,只需要改变该常量值即可。

传递依赖范围

如A依赖于B,B依赖于C,A传递依赖于C,依赖范围关系如下:
在这里插入图片描述
之后会总结Maven项目拆分的相关知识,再说明对于传递依赖范围的理解。

 

关注高校俱乐部,更多精彩内容等着你~

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Maven依赖管理总结 #CSDN博文精选# #依赖管理# #IT# #第三方集成# 的相关文章

  • Helm使用

    Helm 基本概念 Helm 可以理解为 Kubernetes 的包管理工具 可以方便地发现 共享和使用为Kubernetes构建的应用 它包含几个基本概念 Chart 一个 Helm 包 其中包含了运行一个应用所需要的镜像 依赖和资源定义

随机推荐

  • java jhat_java查看工具jhat-windows

    stack false trueTurns off tracking object allocation call stack If allocation site information is not available in the h
  • 问题 E: 栈操作的正确性

    题目描述 对输入序列执行一组栈操作 判断操作是否正确 输入 每行是一个测试用例 表示一个操作序列 操作序列由P和Q两个符号组成 P表示入栈 Q表示出栈 操作序列长度不超过1000 输出 对每个操作序列 若操作序列正确 即操作结束时栈中刚好为
  • 发生交通事故交强险、残疾赔偿金怎么赔?法官列出明细

    2021年9月8日 甲驾驶A车与乙驾驶B车在某路口发生碰撞造成甲受伤及车辆受损的交通事故 经公安交警部门认定 乙负事故全部责任 甲无责 B车在C保险公司处投保交强险 甲治疗终结后 于2022年10月15日经鉴定构成九级伤残和十级伤残 因协商
  • 计算机机房一般在几楼,电梯机房一般在几楼 设备层属于公摊吗

    高楼层的电梯配置都会设有电梯设备层 电梯房设备层一般在几楼 这个要楼层的总高 一般在最顶层或者最底层 但是总楼层比较高 在二十层以上的 一般都有多个电梯房设备层 电梯房设备层设置要点 电梯房设备层主要管理整个楼层的电梯运行 还有一些其他安全
  • leetcode 1. 两数之和

    给定一个整数数组 nums 和一个整数目标值 target 请你在该数组中找出 和为目标值 target 的那 两个 整数 并返回它们的数组下标 你可以假设每种输入只会对应一个答案 但是 数组中同一个元素在答案里不能重复出现 你可以按任意顺
  • EventBus报错:its super classes have no public methods with the @Subscribe annotation

    看源码得知 其注解方法为空 则在当前类或者父类中 没有接收event发送的消息 所以在收到回调的方法中添加如下注解方法 Subscribe threadMode ThreadMode MAIN public void onCollectio
  • 递归模板

    Java public void recur int level int param terminator if level gt MAX LEVEL process result return process current logic
  • Java基础学习过程中出现的错误:

    1 java获得访问者ip 获得的值是ip 0 0 0 0 0 0 0 1 原因 本机地址获取为IPV6的IP 这现象只有在服务器和客户端都在同一台电脑内上才会出现 例如用localhost访问的容时候才会出现 其实作怪的是hosts文件
  • pandas中的Series对象

    Series和DataFrame是pandas中最常用的两个对象 1 可以用Numpy的数组处理函数直接对Series对象进行处理 2 支持使用位置存取元素 使用索引标签作为下标存取元素 每个Series对象实际上都是由两个数组组成 1 i
  • CPU指令集介绍

    1 什么是指令集 参考 http product pconline com cn itbk bjbzj notebook 1109 2522116 html 所谓指令集 就是CPU中用来计算和控制计算机系统的一套指令的集合 而每一种新型的C
  • Model/View开发小结

    老猿Python博文目录 专栏 使用PyQt开发图形界面Python应用 老猿Python博客地址 Model View开发是PyQt和Qt中重要的框架之一 老猿认为另外两个就是信号槽机制和事件机制 这三个是最能体现PyQt和Qt开发特色的
  • 货舱容量分配问题

    4 选做 一架货机有三个货舱 前舱 中舱和后舱 三个货舱所能装载的 货物的最大重量和体积有限制 如表 3 所示 现有四类货物用该货机进行装运 货物的规格以及装运后获得的利润如表 4 所示 并且为了飞机的平衡 三个货 舱装载的货物重量必须与其
  • 最近读了《软件调试的艺术》这本书

    最近读了 软件调试的艺术 这本书 英文名
  • mysql报错Fatal error: Can't open and lock privilege tables: Table 'mysql.host' doesn't exist

    今天在安装mysql后 启动时候没有启动成功 查看了下日志报错如下 root localhost local less var log mysqld log 1 查看报错信息如下 ERROR Fatal error Can t open a
  • LaTeX在论文写作中的常用命令(二)

    在进行数学类论文 尤其是数学建模论文写作时 经常会用到的LaTeX命令如下 1 图片引用 The curve is shown in textbf Figure ref fig 1 图片插入 width 为图片宽度 height为图片宽度
  • 【Vue基础】什么是跨域?如何解决跨域问题?浅浅了解一下什么是登录鉴权

    1 什么是跨域 在了解什么是跨域之前 我们首先要了解一个概念 同源策略 同源策略 同源策略 SOP Same Origin Policy 是一种约定 由 Netscape 公司 1995 年引入浏览器 它是浏览器最核心也最基本的安全功能 现
  • 基于全卷积神经网络对中文手写体汉字骨架的提取

    论文题目 Fully Convolutional Network Based Skeletonization for Handwritten Chinese Characters
  • 进制相互转化

    二进制 由0和1组成 逢二进一 借一当二 八进制 由0 7的数字组成 没有小数部分 十进制 由 0 9的数字组成 不能以0开始 十六进制 以0x开头的数字序列 其后由0 9 A F或a f组成 无小数部分 原码 用第一位表示符号 其余位表示
  • python数据包处理模块_Python3.4.3使用struct模块的pack、unpack对字节数据的处理(压包,解包)...

    struct模块中主要有三个方法struct pack fmt v1 v2 v3 按fmt这个格式把后面数据给封装成指定的数据 返回一个包含了v1 v2等的字节对象 数据是通过fmt格式化后的 参数必须和fmt需要格式化的完全对应起来 st
  • Maven依赖管理总结 #CSDN博文精选# #依赖管理# #IT# #第三方集成#

    大家好 小C将继续与你们见面 带来精选的CSDN博文 在这里 你将收获 将系统化学习理论运用于实践 系统学习IT技术 学习内容涵盖数据库 软件测试 主流框架 领域驱动设计和第三方生态等 离全栈工程师更近一步 精心整理的CSDN技术大咖博文