maven快速入门第十一讲——依赖的传递性
发布日期:2021-06-30 17:54:53 浏览次数:2 分类:技术文章

本文共 5854 字,大约阅读时间需要 19 分钟。

在这一讲中,我详细介绍了依赖的作用范围。而在本讲中,我会介绍依赖的传递性,你听的没错,依赖是具有传递性的。但是,我们也要明白工程与工程之间也是有依赖关系的,正如下图所示。

在这里插入图片描述

依赖具有传递性

在前一讲中,我们使用maven分模块构建了一个聚合工程。接下来,我就要在该聚合工程的基础上编写代码了。

首先,在crm-dao子工程中创建相应的接口与实现类。

  • 接口(比如说ICustomerDao.java)

    package com.meimeixia.crm.dao;public interface ICustomerDao {
    }
  • 以上接口的一个实现类(例如CustomerDao.java)

    package com.meimeixia.crm.dao.impl;import com.meimeixia.crm.dao.ICustomerDao;public class CustomerDao implements ICustomerDao {
    }

然后,同样在crm-service子工程中创建相应的接口与实现类。

  • 接口(比如说ICustomerService.java)

    package com.meimeixia.crm.service;public interface ICustomerService {
    }
  • 以上接口的一个实现类(例如CustomerService.java)

    package com.meimeixia.crm.service.impl;import com.meimeixia.crm.service.ICustomerService;public class CustomerService implements ICustomerService {
    private ICustomerDao customerDao; public void setCustomerDao(ICustomerDao customerDao) {
    this.customerDao = customerDao; } }

此时,你会发现以上CustomerService实现类编写好之后,报错了。

在这里插入图片描述
eclipse提示我们要在crm-service子工程中创建一个ICustomerDao接口,这显然不能够啊!因为这里是要导入crm-dao子工程中的ICustomerDao接口。我们的crm-service子工程将来要把数据存储到数据库中,必然需要依赖crm-dao子工程,所以需要在crm-service子工程的pom.xml文件中添加crm-dao子工程的依赖,即添加crm-dao子工程的工程坐标。大家可以按照下图所示的步骤来进行操作。
在这里插入图片描述
点击OK按钮,再保存一下pom.xml文件,这时你会发现pom.xml文件变成了下面这个样子。
在这里插入图片描述
从中可以清楚地看到添加了一个dependencies节点,该节点中的内容就是crm-dao子工程的工程坐标。而且再仔细查看一下crm-service子工程的结构,你会发现它引入了crm-dao子工程。
在这里插入图片描述
这时,便可以在CustomerService实现类导入crm-dao子工程中的ICustomerDao接口了。

同理,crm-web子工程需要调用业务,所以就需要在其中添加对crm-service子工程的依赖,即需要在crm-web子工程的pom.xml文件中添加crm-service子工程的工程坐标。

在这里插入图片描述
仔细查看crm-web子工程的结构,此时可以看到,它不仅把crm-service子工程依赖进来了,而且还把crm-dao子工程也依赖进来了,这是因为依赖具有传递性
在这里插入图片描述
如果MakeFriends.jar直接依赖于HelloFriend.jar,而HelloFriend.jar又直接依赖于Hello.jar,那么MakeFriends.jar也依赖于Hello.jar,这就是传递性依赖,只不过这种依赖是间接依赖
在这里插入图片描述
还记得在web项目整合Struts2框架时,在web项目的pom.xml文件中只添加了一个struts2-core的依赖,结果发现所有与Struts2开发相关的jar包都引入到该web项目中了吗?
在这里插入图片描述
因为我们的项目依赖struts2-core-2.3.24.jar,而struts2-core-2.3.24.jar又会依赖xwork-core-2.3.24.jar、commons-lang3-3.2.jar等等,所以xwork-core-2.3.24.jar这些jar包也出现在了我们的maven工程中,这种现象我们称之为依赖传递。

你不仅想问了,我是怎么知道struts2-core-2.3.24.jar又会依赖xwork-core-2.3.24.jar、commons-lang3-3.2.jar这些jar包的呢?在本地仓库中找到struts2-core-2.3.24.jar所在的位置,然后你就能看到struts2-core-2.3.24.pom这样一个文件了,它实际上是一个pom.xml文件。

在这里插入图片描述
打开struts2-core-2.3.24.pom文件,你就能看到struts2-core-2.3.24.jar所依赖的那些jar包了,如下图所示。
在这里插入图片描述
其实,也可以借助eclipse来查看struts2-core-2.3.24.jar依赖的层级关系。大家可以按照下图所示的步骤来进行操作。
在这里插入图片描述

使用<exclusion>标签排除jar包冲突

在crm-parent父工程中添加struts2-core和hibernate-core的依赖,如下图所示。

在这里插入图片描述
这时,你会发现有jar包冲突。
在这里插入图片描述
如何解决javassist这个jar包存在版本上的冲突问题呢?可以使用<exclusion>标签来排除jar包冲突问题,大家可以按照下图所示的步骤来进行操作。
在这里插入图片描述
然后,会弹出如下一个窗口,点击其中的OK按钮即可,顺便再保存一下pom.xml文件。
在这里插入图片描述
这时你会发现pom.xml文件变成了下面这个样子。
在这里插入图片描述

依赖的传递范围

如果crm-dao子工程开发完毕了,那么紧接着就要编写JUnit单元测试用例了。相应地,就要在pom.xml文件中添加JUnit的依赖了,并且scope要置为test。

在这里插入图片描述
仔细查看crm-dao子工程的结构,发现junit-4.9.jar这个jar包确实引入了,这是毋庸置疑的。
在这里插入图片描述
这时,我们可以晓得crm-service子工程直接依赖于crm-dao子工程,而crm-dao子工程又直接依赖于junit-4.9.jar,由于依赖具有传递性,那么想必crm-service子工程也会依赖于junit-4.9.jar。也就是说,crm-service子工程中也会引入junit-4.9.jar这个jar包。真的是这样吗?发现并不是这样,仔细查看crm-service子工程的结构,你就知道该工程中并没有引入junit-4.9.jar这个jar包。

卧槽!这与我们所知道的依赖具有传递性不一样啊!这到底是咋一回事啊?其实依赖传递也是有范围的,传递依赖不能无休止的往下面传递下去。

在这里插入图片描述
以上表格中的中间部分即是传递依赖的范围,可见传递依赖不是无休止的往下面传递下去的。

如果我们现在将crm-dao子工程pom.xml文件中的JUnit的依赖修改成下面这个样子,

在这里插入图片描述
那么,不仅crm-dao子工程会引入junit-4.9.jar这个jar包,而且crm-service子工程也会引入这个jar包。
在这里插入图片描述

总结

有同学可能不记得上表中所列出的传递依赖的范围,不记得一点关系都没有,谁的记性都不会那么好。一旦当我们发现项目中需要的某一个依赖(即jar包)没有传递过来时,该怎么办啊?真的是没必要照着上表来修改,你自己在工程中添加对应的依赖就可以了。

总之一句话:如果在依赖传递过程中,导致jar包丢失,我们的做法很简单,就是再导入一次坐标。

依赖传递的两个原则

依赖传递有两个原则,一个是第一声明者优先原则,另一个是路径近者优先原则。下面我会对这两个原则进行详细阐述。

第一声明者优先原则

在Struts2框架与Spring框架进行整合的时候,我们需要导入struts2-spring-plugin-2.3.24.jar这样一个jar包,所以还得在父工程的pom.xml文件中添加该jar包的坐标。

org.apache.struts
struts2-spring-plugin
2.3.24

大家可以按照下图所示的步骤来查看struts2-spring-plugin-2.3.24.jar依赖的层级关系。

在这里插入图片描述
然后,导入与Spring框架开发相关的jar包。例如我故意在父工程的pom.xml文件中添加spring-context-4.2.2.RELEASE.jar的坐标,为什么说故意呢?因为在这儿我仅仅只是用它来说明依赖传递的第一个原则,即第一声明者优先原则。而在实际开发中,本人使用的是spring-framework-4.2.4.RELEASE这个版本的Spring。

org.apache.struts
struts2-spring-plugin
2.3.24
org.springframework
spring-context
4.2.2.RELEASE

照理来说,在各个工程中应该引入spring-beans-3.0.5.RELEASE.jar和spring-beans-4.2.2.RELEASE.jar这两个jar包,结果发现生效的还是通过struts2-spring-plugin-2.3.24.jar依赖进来的版本,即spring-beans-3.0.5.RELEASE这个版本的jar包。

在这里插入图片描述
如果将父工程pom.xml文件中的struts2-spring-plugin-2.3.24.jar与spring-context-4.2.2.RELEASE.jar这俩jar包的坐标颠倒一下位置,那么结果会是什么呢?

org.springframework
spring-context
4.2.2.RELEASE
org.apache.struts
struts2-spring-plugin
2.3.24

结果发现此时生效的是通过spring-context-4.2.2.RELEASE.jar依赖进来的版本了,即spring-beans-4.2.2.RELEASE这个版本的jar包。

在这里插入图片描述
由于spring-context-4.2.2.RELEASE.jar所依赖的spring-beans-4.2.2.RELEASE.jar在前边,所以以它所依赖的spring-beans-4.2.2.RELEASE.jar为准,最终spring-beans-4.2.2.RELEASE这个版本的jar包便添加到了工程中了。这就是所谓的第一声明者优先原则

路径近者优先原则

struts2-spring-plugin-2.3.24.jar跟spring-context-4.2.2.RELEASE.jar都会添加spring-beans的依赖,只不过是struts2-spring-plugin-2.3.24.jar会引入spring-beans-3.0.5.RELEASE这个版本的jar包,spring-context-4.2.2.RELEASE.jar会引入spring-beans-4.2.2.RELEASE这个版本的jar包。如果这时我们直接加入新的依赖,即spring-beans-4.2.4.RELEASE.jar的坐标,结果会是什么呢?

org.springframework
spring-context
4.2.2.RELEASE
org.apache.struts
struts2-spring-plugin
2.3.24
org.springframework
spring-beans
4.2.4.RELEASE

结果发现生效的是直接引入的版本,即spring-beans-4.2.4.RELEASE这个版本的jar包。

在这里插入图片描述
此时,工程中如果要引入spring-beans,可以有以下方法:

  • 通过引入struts2-spring-plugin-2.3.24.jar,它会引入spring-beans-.3.0.5.RELEASE这个版本的jar包,但需要经过的路径为2个节点;
  • 通过引入spring-context-4.2.2.RELEASE.jar,它会引入spring-beans-.4.2.2.RELEASE这个版本的jar包,但需要经过的路径也为2个节点;
  • 如果直接引入spring-beans-4.2.4.RELEASE.jar,那么只需要经过1个节点。

在这里插入图片描述

因此不管spring-beans-4.2.4.RELEASE.jar的位置在哪,工程中始终都是引入spring-beans-4.2.4.RELEASE这个版本的jar包。这就是所谓的路径近者优先原则

转载地址:https://liayun.blog.csdn.net/article/details/103694944 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:maven快速入门第十二讲——版本锁定与版本常量
下一篇:maven快速入门第十讲——使用maven分模块构建工程

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年05月02日 01时04分35秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

利用ffmpeg合并音频和视频 2019-04-30
刷好老毛子系统进不了老毛子系统后台的解决办法 2019-04-30
Parallels Desktop 16 不能联网的解决办法 2019-04-30
ERROR 1292 (22007): Incorrect datetime value: ‘2002‘ for column ‘出版日期‘ at row 1 2019-04-30
SLAM中TUM数据集更改图片名字 2019-04-30
【并发控制】并发控制与分布式锁(redis/zookeeper)实现【图文教程】_ 第1章 2019-04-30
【并发控制】并发控制与分布式锁(redis/zookeeper)实现【图文教程】_ 第2章 2019-04-30
【并发控制】并发控制与分布式锁(redis/zookeeper)实现【图文教程】_ 第3章 2019-04-30
【并发控制】并发控制与分布式锁(redis/zookeeper)实现【图文教程】_ 第4章 2019-04-30
【并发控制】并发控制与分布式锁(redis/zookeeper)实现【图文教程】_ 第5章 2019-04-30
synchronized和CAS锁的区别【图文教程】 2019-04-30
【java】属性别名:@JsonProperty和@JSONField的区别?【图文教程】 2019-04-30
配置nginx只允许域名访问,禁止ip访问【图文教程】 2019-04-30
Java代理【图文教程】_第1章_静态代理 2019-04-30
Java代理【图文教程】_第2章_jdk动态代理 2019-04-30
AOP面向切面编程【图文教程】_第1章 2019-04-30
AOP面向切面编程【图文教程】_第2章 2019-04-30
二叉树之前序、中序、后序和层次遍历【图文教程】 2019-04-30
【java】class内部模块(静态方法,静态块,静态变量,方法块等)执行顺序【图文教程】 2019-04-30
java类的构成 2019-04-30