首页 > 其他分享 >实际上手体验maven面对冲突Jar包的加载规则

实际上手体验maven面对冲突Jar包的加载规则

时间:2024-08-08 13:40:04浏览次数:12  
标签:依赖 Jar rest maven client elasticsearch 模块 加载

一、问题背景

相信大家在日常的开发过程中都遇到过Jar包冲突的问题,emm,在最近处理业务需求时我也遇到了不同版本jar包冲突导致项目加载出错的问题。主要是一个完整的项目会不可避免的使用第三方的Jar包来实现功能开发,各种第三方包之间可能会存在依赖关系,不同版本的依赖就会可能导致依赖间的相互冲突,进而导致整个项目加载的失败。

这篇文章主要记录了本次遇到的问题:即maven在面对不同版本的jar包在pom文件中同时声明会存在加载覆盖的问题,于是通过查询网上相关资料对maven包的加载规则介绍,并通过实际场景对其进行分析验证;

 


 

二、maven加载原则

1.最短路径原则:面对多级(两级及以上)的不同依赖,会优先选择路径最短的依赖; 2.声明优先原则:面对多级(两级及以上)的同级依赖,先声明的依赖会覆盖后声明的依赖; 3.同级依赖中,后声明的依赖会覆盖先声明的依赖;

三、本地验证maven加载原则

1.最短路径原则:使用最短路径加载的前提是,项目中存在两级以上的不同依赖jar包,此时项目会优先加载路径最短的jar包;

 


 

实例验证:分别在common模块和service模块中间接和直接的引入不同版本的elasticsearch-rest-client,观察项目中面对不同路径长度情况下实际加载时所使用的版本情况。 ▪common模块:common模块中引入elasticsearch-rest-high-level-client 依赖包, 而该依赖包它引入了 elasticsearch-rest-client 7.4.2,从而实现在common模块中间接引用该包;

common的pom文件:

    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.4.2</version>
        </dependency>
    </dependencies>
service模块:为了验证不同路径长度下maven的包加载顺序我们在service模块中直接引入elasticsearch-rest-client 6.8.13;

service的pom文件:

    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.8.13</version>
        </dependency>
    </dependencies>
实际加载结果:在IDEA中加载pom文件时,可以在maven管理中看到已经提示jar包冲突;

 


 

mvn dependency:tree: 我们可以通过mvn dependency :tree命令来查看该项目的依赖树,观察发现实际加载的版本是elasticsearch-rest-client 6.8.13,符合maven中的最短路径优先原则;

 


 

 

2. 声明优先原则:声明优先原则的前提是对于两级以上的同级依赖,先声明的依赖会覆盖后声明的依赖包;

 


 

实例验证:针对该原则的验证场景构造不再关注模块是否直接或者间接引用不同版本的es,我们在common模块和service模块中都直接引用不同版本的es,然后通过改变两个模块在pom文件中声明的先后顺序来观察项目启动后实际加载的jar包; ▪common模块:在common模块中直接引入依赖包elasticsearch-rest-client 7.4.2
    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.4.2</version>
        </dependency>
    </dependencies>
service模块:在service模块中引入依赖包elasticsearch-rest-client 6.8.13
    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.8.13</version>
        </dependency>
    </dependencies>
实际加载结果: ▪场景1:我们将common模块在pom文件中先引入,然后将在service模块置于common模块后面引入,观察项目实际加载情况;
    <dependencies>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>backend_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>backend_service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
▪观察加载结果图,发现实际加载的是es-rest-client 7.4.2, 即确实是common模块声明生效,service模块后声明导致其中的es未被加载。符合声明优先原则;

 


 

◦场景2:我们将service模块在pom文件中先引入,然后将在common模块置于service模块后面引入,观察项目实际加载情况;;
    <dependencies>
         <dependency>
            <groupId>org.example</groupId>
            <artifactId>backend_service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>backend_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
▪观察项目实际加载结果图,发现实际加载的是es-rest-client 6.8.13, 即确实是模块声明生效,common模块后声明导致其中的es未被加载。发现符合声明优先原则;

 


 

◦声明优先原则场景验证结束

3. 同级依赖中后加载覆盖先加载原则

 


 

实例验证:为了构造在同级依赖中的加载场景我们在项目中直接引入两个不同es版本的依赖,然后同样通过改变两个es版本在pom中的声明顺序来观察项目实际加载的es版本。 ▪场景1:我们首先验证client 7.4.2依赖包在client 6.8.13之前声明的情况;
    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.4.2</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.8.13</version>
        </dependency>
    </dependencies>
▪观察maven的实际加载结果如下,发现项目中实际加载的es-rest-client 版本是6.8.13,先声明的7.4.2版本并未实际加载到项目中。符合同级依赖中后加载覆盖先加载原则。

 


 

▪场景2:然后我们改变声明顺序,将client 6.8.13依赖包在client 7.4.2之前声明;
    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.8.13</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.4.2</version>
        </dependency>
    </dependencies>
▪观察maven实际加载结果如下,发现项目中实际加载的es-rest-client 版本是7.4.2,先声明的6.8.13版本并未实际加载到项目中。符合同级依赖中后加载覆盖先加载原则。

 


 

四、常见异常

Jar发生冲突后在程序启动时常见异常报错,下面四种异常是能够直观表征Jar包加载冲突

◦程序抛出java.lang.ClassNotFoundException异常; ◦程序抛出java.lang.NoSuchMethodError异常; ◦程序抛出java.lang.NoClassDefFoundError异常; ◦程序抛出java.lang.LinkageError异常等;

五、总结

之前只是浅层的了解maven包的加载,没有结合具体的加载原则进行系统的学习验证,正好通过需求开发中遇到依赖冲突相关问题对maven的加载原则进行探究。ok,明白啦!

 

 

标签:依赖,Jar,rest,maven,client,elasticsearch,模块,加载
From: https://www.cnblogs.com/Jcloud/p/18348758

相关文章

  • Xcode动态功能加载:深入探索与实践指南
    Xcode动态功能加载:深入探索与实践指南引言在iOS应用程序开发中,动态功能加载是一项高级技术,它允许开发者在运行时动态加载和卸载应用程序的功能模块。这种技术可以显著提高应用程序的灵活性和可扩展性。本文将详细介绍如何在Xcode中实现应用的动态功能加载,包括概念解释、步......
  • 【13.PIE-Engine案例——加载Landsat8 Collection2 SR数据集】
    原始链接原始路径欢迎大家登录航天宏图官网查看本案例原始来源结果展示具体代码/***@File:Landsat8Collection2SR*@Time:2021/5/24*@Author:piesat*@Version:1.0*@Contact:400-890-0662*@License:(C)Copyright航......
  • 【15.PIE-Engine案例——加载Landsat 8 SR数据集】
    加载Landsat8SR数据集原始路径欢迎大家登录航天宏图官网查看本案例原始来源最终结果具体代码/***@File:Landsat8SRImages*@Time:2020/7/21*@Author:piesat*@Version:1.0*@Contact:400-890-0662*@License:(C)Copyr......
  • 高性能图片懒加载
    之前都是监听页面滚动,使用window.addEventListener("scroll", () => {})然后判断图片是否进入可视区域,在进行加载图片(data-src自定义属性,赋值给src属性)这里介绍一个高性能的图片懒加载方式,浏览器原生自带的IntersectionObserverAPI(兼容性也挺好),用于异步检测目标元素与父级......
  • 对于找到的每封唯一电子邮件,加载所有相关附件
    我正在尝试自动创建包含与电子邮件关联的所有附件的电子邮件。我有一个Excel文档,正在引用电子邮件和附件。index=0counter=0foremailinemails:mailItem=olApp.CreateItem(0)mailItem.Subject=mailItem.BodyFormat=1mailItem.Body=......
  • Python & Selenium 4 & Edge 浏览器 |加载个人浏览器配置文件(包括cookie)
    使用Selenium4,我尝试加载我的个人浏览器配置文件(包括cookie),以便它可以加载到我之前登录过的网站。我正在使用边缘浏览器。在测试我的代码片段时,它似乎没有加载我的浏览器配置文件,而是创建一个新的(配置文件1)。我已确保配置文件的路径是正确的。我的代码片段:edge_opt......
  • ModuleNotFoundError:加载模型时没有名为“sklearn”的模块
    importpicklemodell=pickle.load(open('model.pkl','rb'))我想加载并打开该文件,以便我应用函数来检查AI模型,但它们显示ModuleNotFoundError:Nomodulenamed'sklearn'错误。我不知道为什么我有这个错误,不需要odsklearn。当尝试运行需要安装Scikit-......
  • Maven依赖管理【后端 2】
    Maven依赖管理详解在Java项目开发中,依赖管理是一个至关重要的环节。Maven作为Java世界中最流行的项目管理工具之一,通过其强大的依赖管理机制,极大地简化了项目构建和依赖管理的复杂性。本文将详细介绍Maven的依赖配置、依赖传递以及依赖范围等核心概念。4.1依赖配置依赖......
  • 在Gradle8中使用阿里云maven仓库、jitpack仓库
    编辑settings.gradlepluginManagement{repositories{google{content{includeGroupByRegex("com\\.android.*")includeGroupByRegex("com\\.google.*")includeGroupByRe......
  • 类加载机制
    类加载机制类加载器(ClassLoader):类加载器负责将.class文件加载到JVM中。Java虚拟机使用一个分层的类加载器架构,通常包括以下几种类型的类加载器:启动类加载器(BootstrapClassLoader):负责加载Java核心库类,如java.lang.Object。扩展类加载器(ExtensionClassLoader):负责加载扩展目录......