找回密码
 会员注册
查看: 20|回复: 0

MAVEN依赖的优先原则

[复制链接]

2

主题

0

回帖

7

积分

新手上路

积分
7
发表于 2024-10-12 21:05:57 | 显示全部楼层 |阅读模式
MAVEN依赖的优先原则 362 Maven 依赖可以分为如下几部分:直接依赖,就是本项目 dependencies 部分的依赖间接依赖,就是本项目 dependencies 部分的依赖所包含的依赖依赖管理,就是本项目 dependency management 里面的依赖parent 的直接依赖parent 的间接依赖parent 的依赖管理bom 的直接依赖(一般没有)bom 的间接依赖(一般没有)bom 的依赖管理PS:bom 就是工程项目中最外层主 POM ,也就是 dependencyManagement 那个 POM一、 MAVEN 依赖三大原则1.1 最短路径优先原则Maven 依赖遵循最短路径优先原则,当项目直接依赖一个 C-api-1.0 和 A-api-2.1 包,并且 C-api-1.0 有如下间接依赖关系:C-api-1.0 —> B-api-1.0 —> A-api-1.1 这时候项目里包含了 A-api 的 1.1 和 2.1 两个版本,由于存在最短路径原则明显 Project —> A-api-2.1 短于 Project —> C-api-1.0 —> B-api-1.0 —> A-api-1.1 故 Project 项目里会使用 A-api-2.1示例项目中包含如下依赖          org.springframework.boot      spring-boot-starter              org.apache.poi      poi-ooxml      3.10-FINAL              QLExpress      com.alibaba      3.2.2    其中 poi-ooxml 存在如下依赖关系:poi-ooxml-->poi-->commons-logging (版本 1.1 ) QLExpress 存在如下依赖关系:QLExpress —> commons-logging (版本 1.1.1 ) 由于存在最短路径原则,明显 QLExpress —> commons-logging 路径更短,项目会使用 commons-logging 的 1.1.1 版本1.2 POM 文件中申明顺序优先原则Maven 依赖遵循 POM 文件中申明顺序优先原则,当项目里存在直接依赖 C-api-1.0 和 B-api-1.0 其中存在如下间接依赖关系:C-api-1.0 —> A-api-2.1 B-api-1.0 —> A-api-1.1 这时项目间接依赖了 A-api 的 2.1 和 1.1 两个版本,由于存在 POM 文件中申明顺序优先原则,故项目中会使用 A-api-2.1示例项目中存在如下依赖      org.springframework.boot    spring-boot-starter        org.apache.poi    poi-ooxml    3.10-FINAL        org.apache.poi    poi-scratchpad    3.17-beta1  其中 poi-ooxml 依赖了包 poi ,poi-scratchpad 也依赖了 poi 包,但是 poi-ooxml 依赖了 poi 包的 3.10-FINAL 版本, poi-scratchpad 依赖了 poi 包的 3.17-beta1 版本,由于存在申明顺序优先原则,项目会使用 poi 包的 3.10-FINAL 版本1.3 覆盖优先原则Maven 依赖遵循覆盖优先原则,项目父 POM 中直接依赖包 A-api-1.1 ,子模块 Module A 的 parent 直接依赖了项目的 POM ,但是同时也直接依赖了 A-api-1.2 。由于存在覆盖优先原则子模块 Module A 中会优先使用 A-api-1.2 而不是父POM的 A-api-1.1在以上项目工程下,新建一个子工程,在子工程POM添加如下依赖          org.apache.poi      poi      5.2.3    由于外部工程依赖了 poi 包的 3.10-FINAL ,但是子工程依赖了 poi 的 5.2.3 版本,故整体包依赖会包含poi的两个版本,但是在子工程中使用的是 5.2.3怎么证明我们在子工程使用的是 poi 的 5.2.3 版本呢?我们在子工程可以写一个 main 方法调用方法 org.apache.poi.util.Units 类的 columnWidthToEMU 方法,在父工程同样调用这个方法,发现父工程这个方法报错不存在。import org.apache.poi.util.Units;public class Test {    public static void main(String[] args) {        Units.columnWidthToEMU(1);    }}二、 MAVEN 依赖冲突常见报错2.1 ClassNotFoundException当项目启动时出现 ClassNotFoundException 这样的错误,表示由于项目使用的包版本下找不到当前需要的类 1、调用 class 的 forName 方法时,找不到指定的类。2、 ClassLoader 中的 findSystemClass() 方法时,找不到指定的类。3、 ClassLoader 中的 loadClass() 方法时,找不到指定的类。2.2 NoSuchMethodErrorNoSuchMethodError 就是程序在运行中找不到运行的方法导致的 1、有可能发生的就是 jar 冲突,可能是两个高低版本的 jar 包导致。2、有可能是有两个 jar 包有相同的类与方法,导致程序调用过程中找不到正确的方法。三、Maven 依赖加载流程Maven 依赖加载流程如下首先,将 parent 的直接依赖,间接依赖,还有依赖管理,插入本项目,放入本项目的直接依赖,间接依赖还有依赖管理之前。对于直接依赖,如果有 version,那么就依次放入 DependencyMap 中。如果没有 version ,则从依赖管理中查出来 version,之后放入 DependencyMap 中。key 为依赖的 groupId + artifactId, value 为 version ,后放入的会把之前放入的相同 key 的 value 替换。对于每个依赖,各自按照步骤 1 和 2 加载自己的 pom 文件,但是如果第一步中的本项目 dependency management 中有依赖的版本,使用本项目 dependency management 的依赖版本,生成 TransitiveDependencyMap ,这里面就包含了所有的间接依赖。所有间接依赖的 TransitiveDependencyMap , 对于项目的 DependencyMap 里面没有的 key ,依次放入项目的 DependencyMap 。如果 TransitiveDependencyMap 里面还有间接依赖,那么递归执行步骤 3 和 4 。由于是先放入本项目的 DependencyMap ,再去递归 TransitiveDependencyMap ,这就解释了 Maven 依赖的最短路径原则。可用文中 1.1 做示例如下:四、总结本次主要讲解了 maven 依赖包含的几大部分,以及 maven 依赖三大原则,并且对每种依赖原则都做了具体图解和示例,方便我们可以直接在项目中运行调试。期间对 maven 冲突导致的常见报错进行讲解方便我们在开发过程中快速定位问题。最后讲解了 maven 加载包进入项目中的整个流程,并按照文中 1.1 所讲的“最短路径优先原则“做为示例图解,进而加深对 maven 加载包流程的理解。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-25 13:35 , Processed in 0.744180 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表