美文网首页Maven
面对他,消灭他-搞定Maven依赖冲突

面对他,消灭他-搞定Maven依赖冲突

作者: 晏子小七 | 来源:发表于2020-04-10 11:32 被阅读0次

    因:

    了解出现Maven依赖冲突的原因首先了解一下Maven的仲裁机制:

    • 优先按照依赖中<dependencyManagement>元素中指定的版本进行仲裁(此时下面2个无效)
    • 无版本声明,则按照“最短路径”原则进行仲裁,选择依赖树中路径最短的版本
    • 如果路径长度一致,则按照“第一声明”原则进行仲裁,即pom中最先声明的版本

    原因总结:

    1. 传递依赖导致不同的jar包冲突——maven会采用‘最短路径’选择jar。如果排除的是旧版本的jar包,直接调用最新jar有的方法,就会报ClassnotFound错误。


      最短路径

      如图,我们显示依赖了 spring-boot1.5.9,和spring-core4.0.8(当然这种情况在正常情况下不会发生)
      在这种情况,根据Maven的最短依赖路径原则,会使用spring-core4.0.8
      当在启动项目的时候会报错:


      项目报错
    1. 不同的jar包,出现相同的类路径,此时JVM运行时会不知道执行哪个类,会报 java.lang.AbstractMethodError: javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V类似运行时异常。
    2. 在运行期,很有可能出现依赖A在执行过程中调用C(1.0)以前有但是升级到C(1.1)就缺失的类c,导致运行期失败,出现很典型的依赖冲突时的NoClassDefFoundError错误。
    3. 如果是升级后出现原有的方法被修改而不存在的情况时,就会抛出NoSuchMethodError错误。

    解:

    1. 首先可以借助Maven查看依赖的依赖树来分析一下:手动:mvn dependency:tree,或者使用IDEA的Maven Helper插件Dependency Analyzer插件来可视化地分析依赖关系,或者 mvn dependency:tree -Dverbose查看依赖树。这个过程后可以明确哪些dependency引入了可能会冲突的依赖。


      analyzer解决冲突
    2. Maven Helper插件就找到冲突jar包,然后在对应标红版本的jar包上面点击execlude,就可以将该jar包排除出去。


      dependencytree
    3. 使用ctrl+shift+alt+n 查找类路径所在的jar包,把对应的jar包在pom中排除。

    其他解决方案:

    ①. 统一版本:为jar包指定一个版本,所有用到的都会是这个版本。操作如下:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.0.0.RELEASE</version>
    </dependency>
    
    

    统一配置:

    <properties>
        <spring.version>4.1.1.RELEASE</spring.version>
    </properties>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    
    

    ②. 排除加载:就是在别的用到这个jar包的地方加上说明,告诉它不用自己加载依赖用别人的。 如下: 如果我们不想通过 A->B->C>D1 引入 D1 的话,那么我们在声明引入 A 的时候将 D1 排除掉 举个例子:将 zookeeper 的 jline 依赖排除

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.3.1</version>
            <exclusions>
                <exclusion>
                    <groupId>jline</groupId>
                    <artifactId>jline</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    
    

    相关文章

      网友评论

        本文标题:面对他,消灭他-搞定Maven依赖冲突

        本文链接:https://www.haomeiwen.com/subject/wyolmhtx.html