Maven 依赖调解源码解析(四):传递依赖,第一声明者优先
2023-03-15 23:25:36 时间
场景
路径最近者优先原则不能解决所有问题,比如这样的依赖关系:A-> C->X(1.0)、A->D->X(2.0),X(1.0)和 X(2.0)的依赖路径长度是一样的,都为 2。那么到底谁会被解析使用呢?在 Maven 2.0.8 及之前的版本中,这是不确定的,但是从 Maven 2.0.9 开始,为了尽可能避免构建的不确定性,Maven 定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度相等的前提下,在 POM 中依赖声明的顺序决定了谁会被解析使用,顺序最靠前的那个依赖优胜。该例中,C 的依赖声明在 D 之前,那么 X(1.0)就会被解析使用。
B、C 、D 的 pom.xml 内容均不变。A 的 pom.xml 内容改动一下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mavenDependencyDemo</artifactId>
<groupId>org.example</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>A</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>C</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>D</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
源码
和前面的分析方法一致,我们先执行 mvn dependency:tree -Dverbose 命令,看看输出:
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------------< org.example:A >----------------------------
[INFO] Building A 1.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A ---
[INFO] org.example:A:jar:1.0
[INFO] +- org.example:C:jar:1.0:compile
[INFO] | - org.example:X:jar:1.0:compile
[INFO] - org.example:D:jar:1.0:compile
[INFO] - (org.example:X:jar:2.0:compile - omitted for conflict with 1.0)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.017 s
[INFO] Finished at: 2021-11-20T15:52:36+08:00
[INFO] ------------------------------------------------------------------------
可以看出,A 依赖了 X(1.0),而 X(2.0)被忽略了。关键语句变成了
(org.example:X:jar:2.0:compile - omitted for conflict with 1.0)
看起来还是 omitted for conflict with 这个信息。基于前面的分析,很可能进入了这段代码:
那自然而然,resolved 就是 X(1.0),我们直接进入源码分析:
很明显看出,如果两个依赖的路径深度相同,保留最先声明的依赖。
小结
有了前面的分析经验,这个原则的分析就很简单了,仍然是 NewestConflictResolver 进行调解。 这个「小于等于」就很有灵性,同时实现了传递依赖的路径最近者优先和第一声明者优先这两个原则。
相关文章
- Spring Boot 把 Maven 干掉了
- 适用于应用开发的十大优秀Java IDE
- 用 Java 训练深度学习模型,原来可以这么简单!
- 阿里云一面:并发场景下的底层细节 - 伪共享问题
- 「跬步千里」详解 Java 内存模型与原子性、可见性、有序性
- 以 DEBUG 方式深入理解线程的底层运行原理
- Java 线程和操作系统的线程有啥区别?
- Java 集合框架体系总览
- Java 中为什么要设计包装类
- 读懂框架设计的灵魂—Java反射机制
- 从头捋了一遍 Java 代理机制,收获颇丰
- Java开发学习(五十)----MyBatisPlus快速开发之代码生成器解析
- Java开发学习(四十九)----MyBatisPlus更新语句之乐观锁
- Java开发学习(四十七)----MyBatisPlus删除语句之多记录操作
- Java开发学习(四十八)----MyBatisPlus删除语句之逻辑删除
- Java开发学习(四十六)----MyBatisPlus新增语句之id生成策略控制及其简化配置
- Java开发学习(四十五)----MyBatisPlus查询语句之映射匹配兼容性
- Java开发学习(四十四)----MyBatisPlus查询语句之查询条件
- Java开发学习(四十三)----MyBatisPlus查询语句之查询投影
- Java开发学习(四十二)----MyBatisPlus查询语句之条件查询