• 一招解决所有依赖冲突


    背景介绍

    最近遇到了这样一个问题,我们有一个 jar 包 common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。

    一看是 NoSuchMethodError,意思是 DisJunction 里 init 方法没找到,但是我检查了代码是有这个方法的啊。

    问题定位

    当时百度了一下,都说这种情况一般是 jar 包冲突了,但是本地看来下没有 jar 包版本都一致,没有冲突啊,百思不得其解。于是写了个代码看看这个报找不到方法的类到底有没有这个方法。

    Constructor[] constructors = Disjunction.class.getConstructors();
        for (Constructor constructor:constructors){
        //查看类的构造器方法
           log.error("find monitor bug:{}",constructor);
        }
        Class targetclass = Disjunction.class;//可以用自己想知道的类替换
        String className = targetclass.getName();
        className = className.replace('.', '/');
        String resource = "/" + className + ".class";
        URL url = targetclass.getResource(resource);
        //查看类的全路径
        log.error("find monitor bug:{}",url.getFile());
    
    

    打印出来后发现类全路径竟然不是我的包里的,是一个 agent.jar 里面的。

    问了下才知道原来是运维添加了一个 agent 到线上环境,里面的 byte-buddy 依赖和我的冲突了。

    如果是本地冲突的话,也可以使用 IDEA 里的 Maven Helper 插件,它可以清晰的指出某个包被哪几个包依赖。

    解决方案:

    在看解决方案之前先来回顾一下Maven的依赖原则:

    • 最短路径优先

    即如果我 A->B->C->X1.0,D->E->X2.0,我项目里引入了 A 和 D,那么我的 X 版本是用的 2.0,因为 X2.0 路径最短。

    • 申明顺序优先

    如果 A-B-X(1.0) ,A-C-X(2.0) 这样的路径长度一样怎么办呢?这样的情况下,maven 会根据 pom 文件声明的顺序加载,如果先声明了 B,后声明了 C,那就最后的依赖就会是 X(1.0)

    解决方案 1:

    maven 依赖的顺序是路径优先,所以我们可以在项目的 pom 文件里直接申明版本,这样就比项目里的引入的 jar 包里再引入的依赖优先级要高些。

    这种方案的缺点就是因为我这个基础 jar 包好几个项目再用,需要每个项目都要修改。

    解决方案 2:

    使用 maven 插件 maven-shade-plugin

     <plugin>
                    <artifactId>maven-shade-pluginartifactId>
                    <executions>
                        <execution>
                            <phase>packagephase>
                            <goals>
                                <goal>shadegoal>
                            goals>
                            <configuration>
                                <artifactSet>
                                    <includes>
                                       //替换的范围,只替换下面两个包 <include>net.bytebuddy:byte-buddyinclude>
                                        <include>net.bytebuddy:byte-buddy-agentinclude>
                                    includes>
                                artifactSet>
                                <createSourcesJar>truecreateSourcesJar>
                                <relocations>
                                    <relocation>
                                // 将net.bytebuddy依赖重命名为cn.mmc.net.bytebuddy
                                <pattern>net.bytebuddypattern>
                                        <shadedPattern>cn.mmc.net.bytebuddyshadedPattern>
                                    relocation>
                                relocations>
                            configuration>
                        execution>
                    executions>
                plugin>
    

    这种做法就是将原有依赖的 jar 包都重命名一下,比如里面的类是 net.bytebuddy.DisJunction,用这个插件后就变为了 cn.mmc.net.bytebuddy.DisJunction,这样类的全路径不一样,就彻底杜绝了依赖冲突的情况。

    另外上面的 includes 是指仅指定替换某些依赖里包名是 net.bytebuddy,否则所有包含了 net.bytebuddy 的都会被重命名,这样打出来的 jar 包就会非常大。

    总结

    为了一劳永逸,我使用了第二种方案 maven-shade-plugin 的方式,发布之后依赖冲突的问题就解决了。


    __EOF__

  • 本文作者: 女友在高考
  • 本文链接: https://www.cnblogs.com/javammc/p/16935071.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    Go语言将string解析为time.Time时两种常见报错
    数据结构---哈希表基本操作浅记
    库函数和头文件
    python 终端输出带颜色的文字(ANSI颜色、背景颜色、字体效果等等)
    Python 完美诠释"高内聚"概念的 IO 流 API 体系结构
    《中国垒球》:棍网球委员会·垒球联盟
    HTML+CSS+JS网页设计期末课程大作业—— 绿色化妆品HTML+CSS+JavaScript
    挑战52天背完小猪佩奇(第03天)
    Golang PDF转图片 拼接长图 压缩PDF及图片 输出JPEG
    MySQL逻辑架构
  • 原文地址:https://www.cnblogs.com/javammc/p/16935071.html