Maven快速入门(五)Maven的依赖管理
前面我们讲了maven项目中的最重要的文件:pom.xml 配置文件相关内容。介绍了pom 是如何定义项目,如何添加依赖的jar 包的等。
我们知道,在Maven的生命周期中,存在编译、测试、运行等过程,那么有些依赖只用于测试,比如junit;有些依赖编译用不到,只有运行的时候才能用到,比如mysql的驱动包在编译期就用不到(编译期用的是JDBC接口),而是在运行时用到的;还有些依赖,编译期要用到,而运行期不需要提供,因为有些容器已经提供了,比如servlet-api在tomcat中已经提供了,我们只需要的是编译期提供而已。
那么Maven是如何管理各个jar包的依赖关系,jar包之间的依赖传递和依赖冲突呢?所以接下来就讲一讲maven的依赖管理。
一、声明依赖
Maven 项目使用pom.xml 文件,可以方便的管理项目中所有依赖的jar包,之前也介绍过pom.xml 文件是如何定义依赖的。下面就以一段 junit依赖声明,演示pom.xml 是如何定义相关依赖的:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<type>jar</type>
<scope>test</scope>
<optional>false</optional>
<exclusions>
<exclusion></exclusion>
</exclusions>
</dependency>
</dependencies>
上面的示例我们定义了junit的依赖,而且junit只在测试阶段生效。具体配置参数如下:
- type:依赖类型,对应构件中定义的 packaging,可不声明,默认为 jar;
- scope:依赖范围,大致有compile、provided、runtime、test、system等几个;
- optional:依赖是否可选;
- exclusions:排除传递依赖。
总结说来,在pom.xml 配置文件中,配置节点引入了节点,它主要管理依赖的范围。大致有compile、provided、runtime、test、system等几个。引入 节点排除某些依赖。解决了控制各个jar包的依赖范围,jar包之间的依赖传递和依赖冲突的问题。
二、依赖范围
Maven在执行不同的命令时(mvn package,mvn test,mvn install ……),会使用不同的 classpath,Maven 对应的有三套 classpath,即:编译classpath、测试classpath,运行classpath。我们可在dependency中的scope元素中进行配置。从而决定了该依赖构件会被引入到哪一个 classpath 中。默认为:compile。Maven提供的依赖范围如下:
- compile:编译依赖范围,默认值。此选项对编译、测试、运行三种 classpath 都有效,如 hibernate-core-3.6.5.Final.jar,表明在编译、测试、运行的时候都需要该依赖;
- test:测试依赖范围。只对测试有效,表明只在测试的时候需要,在编译和运行时将无法使用该类依赖,如 junit;
- provided:已提供依赖范围。编译和测试有效,运行无效。如 servlet-api ,在项目运行时,tomcat 等容器已经提供,无需 Maven 重复引入;
- runtime:运行时依赖范围。测试和运行有效,编译无效。如 jdbc 驱动实现,编译时只需接口,测试或运行时才需要具体的 jdbc 驱动实现;
- system:系统依赖范围。和 provided 依赖范围一致,也是编译和测试有效,需要通过 显示指定,且可以引用环境变量;
- import:导入依赖范围。使用该选项,通常需要 pom,将目标 pom 的 dependencyManagement 配置导入合并到当前 pom 的 dependencyManagement 元素。
需要注意的是,在打包阶段,使用的是运行classpath。即引入到运行classpath中的Maven依赖会被一起打包。
三、依赖传递
所谓依赖传递,就是A依赖B,B依赖C,A就间接依赖C,那么A与C直接的依赖关系就叫传递性依赖。
直接依赖又叫第一直接依赖,传递性依赖又叫第二直接依赖,其中第一直接依赖和第二直接依赖的依赖范围,决定了传递性依赖的依赖范围。
下面使用hibernate-core的依赖关系详细介绍所谓的依赖传递:

如上图所示,hibernate-core 依赖 hibernate-commons-annotations ,而 hibernate-commons-annotations 又依赖 slf4j-api ,hibernate-core 对 slf4j-api 的依赖就是传递依赖。pom.xml 文件中我们只需要引入 hibernate-core 构件的依赖,Maven 会自动为我们引入依赖jar包及传递依赖的jar包,无需再手动引一遍相关依赖。所以不用担心依赖冲突的问题。
那么如何判定一个间接依赖是否有必要被引入呢?间接依赖被引入后其依赖范围又是什么呢?
其实很简单,就是通过第一直接依赖的依赖范围和第二直接依赖的依赖范围之间的关系,来判定是否有必要引入间接依赖以及确定引入间接依赖后其依赖范围,如下表所示:

所以,通过上表我们可以发现:
1)第二直接依赖的依赖范围为compile : 传递依赖的依赖范围同第一直接依赖的依赖范围一样。
2)第二直接依赖的依赖范围为test : 传递依赖不会被引入。
3)第二直接依赖的依赖范围为provided : 只有当第一直接依赖的依赖范围亦为provided时,传递依赖才会被引入,且依赖范围依然是provided。
4)第二直接依赖的依赖范围为runtime : 除了第一直接依赖的依赖范围为compile时传递依赖的依赖范围为runtime外,其余情况下,传递依赖的依赖范围同第一直接依赖的依赖范围一样。
四、依赖冲突
通常我们不需要关心传递性依赖,但是当多个传递性依赖中有对同一构件不同版本的依赖时,如何解决呢?通常我们有一下两个原则:
- 短路径优先:假如有以下依赖:A -> B -> C ->X(版本 1.0) 和 A -> D -> X(版本 2.0),则优先解析较短路径的 X(版本 2.0);
- 先声明优先:即谁先声明,谁被解析。
针对依赖冲突中的“短路径优先”,那如果我们就想使用长路径的依赖怎么办呢?这时可以使用依赖排除元素,显示排除短路径依赖。在非冲突的情况下,这种方法同样有效。
五、解决依赖冲突
一般情况下我们不需要关心依赖的问题。而当依赖出问题时,我们需要知道该如何解决依赖冲突。解决依赖冲突的方式如下:
(1)首先,使用:mvn dependency:tree 命令查看项目的依赖列表,
(2)然后,通过依赖列表,找出冲突的jar包。
(3)最后,可选依赖 option或是排除依赖 exclusions 处理相关冲突。
1.可选依赖 option
通过项目中的pom.xml中的dependency下的option元素中进行配置,只有显式地配置项目中某依赖的option元素为true时,该依赖才是可选依赖;不设置该元素或值为false时,作用是:当某个间接依赖是可选依赖时,无论依赖范围是什么,其都不会因为传递性依赖机制而被引入。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<!-- optional=true,依赖不会传递,该项目依赖devtools;之后依赖boot项目的项目如果想要使用devtools,需要重新引入 -->
<optional>true</optional>
</dependency>
上面的示例,当optional=true,devtools的依赖不会传递,该项目依赖devtools;之后依赖该项目的项目则不会依赖devtools组件,如果想要使用devtools,需要重新引入。
2.排除依赖 exclusions
我们知道,由于Maven的的传递性依赖机,有时候第三方组件B的C依赖由于版本(1.0)过低时。我们期望能够将该间接依赖直接剔除出去,这样不会影响到项目中其他依赖组件。这时可以通过exclusions元素实现。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
上面,我们排除了spring-core组件忠的commons-logging。
最后
以上,我们就把Maven的依赖关系,Jar包之间的依赖传递和依赖冲突介绍完了。
Maven快速入门(五)Maven的依赖管理的更多相关文章
- (4)Maven快速入门_4在Spring+SpringMVC+MyBatis+Oracle+Maven框架整合运行在Tomcat8中
利用Maven 创建Spring+SpringMVC+MyBatis+Oracle 项目 分了三个项目 Dao (jar) Service (jar) Controller (web) ...
- Maven快速入门(一)Maven介绍及环境搭建
做开发的程序员都知道,在系统开发需要各自各样的框架.工具.其中有一种工具不管你是初级程序员还是高级程序员都必须熟练掌握的,那就是项目管理工具(maven.ant.gradle).接下来就总结Maven ...
- Maven快速入门(二)手动创建maven项目hellomaven
之前讲过Maven介绍及环境搭建,介绍了maven的作用和如何搭建maven环境.接下来就以一个helloworld的例子来说一说如何创建maven项目以及maven项目的项目结构,最后讲maven如 ...
- Maven快速入门(三)Maven的坐标和仓库
之前通过一个helloworld的例子来说一说如何创建maven项目以及maven项目的项目结构,然后讲maven如何编译运行项目.接下来介绍maven中几个比较重要的概念:坐标和仓库.Maven快速 ...
- Java实战及解析 — Maven快速入门
五分钟快速入门 mvn --version mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -Darche ...
- (1)Maven快速入门_1maven安装
Maven 快速入门 1.1 Maven官网下载 windows 系统 下载 下图红色框选处. 下载到本地解压, 创建一个本地maven仓库的目录 maven_lib 配置Maven的环境变量 ...
- (5)Maven快速入门_5maven聚合与继承_scope依赖范围
多个maven项目实现统一管理, maven 插件jar继承自父的maven项目.对maven中jar的版本进行管理. 1.创建一个项目来管理多个maven项目 new ----maven Proje ...
- Maven——快速入门手册(学习记录)
前言: 前段时间进行了一点maven的入门学习,在这里做个记录,希望能帮到一些正在学习的朋友们.maven版本为3.3.9.希望大家觉得好的点个赞,觉得不好的多提提意见和建议做个交流.这里也贴出我学习 ...
- Maven快速入门使用
1. Maven 介绍 1.1 为什么使用 Maven 由于 Java 的生态非常丰富,无论你想实现什么功能,都能找到对应的工具类,这些工具类都是以 jar 包的形式出现的,例如 Spring,Spr ...
随机推荐
- P6563-[SBCOI2020]一直在你身旁【dp,单调队列】
正题 题目链接:https://www.luogu.com.cn/problem/P6563 题目大意 长度为\(n\)的序列\(a_i\),现在有一个随机\([1,n]\)的整数,每次你可以花费\( ...
- P3980-[NOI2008]志愿者招募【费用流】
正题 题目链接:https://www.luogu.com.cn/problem/P3980 题目大意 \(n\)天,第\(i\)天需要\(A_i\)个志愿者.有\(m\)种志愿者,第\(i\)种从\ ...
- WPF进阶技巧和实战03-控件(1-控件及内容控件)
所有控件都继承自System.Windows.Controls.Control类,这个类添加一些基本结构: 设置控件内容对齐方式 (HorizontalContentAlignment,Vertica ...
- mysql从零开始之MySQL DELETE 语句
MySQL DELETE 语句 你可以使用 SQL 的 DELETE FROM 命令来删除 MySQL 数据表中的记录. 你可以在 mysql> 命令提示符或 PHP 脚本中执行该命令. 语法 ...
- linux 信号与处理
一.linux信号是什么 基本概念 信号是事件发生时对进程的通知机制,也就是所谓的软件中断.信号和硬件的中断类似,是软件层对中断机制的模拟,在多数情况下是无法预测信号产生的时间,所以软件层提供了一种处 ...
- Linux tomcat 部署war包
将打包好的 war包放在 webapps的文件夹下 在tomcat/conf 文件夹下的 server.xml 里填加 <Context path="" docBase=&q ...
- F1西班牙大奖赛-加泰罗尼亚赛道地图及简介
背景 银石双赛结束,第二轮三连赛的最后一场将转战西班牙,第50届F1西班牙大奖赛将于本周末(正赛2020-08-15)在加泰罗尼亚赛道上演. 作为近年来F1承办季前测试的赛道,所有人都对这里再熟悉不过 ...
- Go 语言实现 gRPC 的发布订阅模式,REST 接口和超时控制
原文链接: 测试小姐姐问我 gRPC 怎么用,我直接把这篇文章甩给了她 上篇文章 gRPC,爆赞 直接爆了,内容主要包括:简单的 gRPC 服务,流处理模式,验证器,Token 认证和证书认证. 在多 ...
- [Beta]the Agiles Scrum Meeting 7
会议时间:2020.5.21 20:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 issue yjy 暂无 tq 新增功能:添加.选择.展示多个评测机,对新增功能进行测试 评测部分增加 ...
- 将manjaro作为主力开发系统,我遇到了哪些坑。
首先遇到的问题就是企业微信. 最开始几天,我直接去安装企业微信和微信,安装全都报错了. 无奈之下,只好安装了virtual box,装了一个win7,可以正常使用微信,企业微信,最开始蛋疼的地方是,企 ...