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

因:

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

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

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

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

  • 不同的jar包,出现相同的类路径,此时JVM运行时会不知道执行哪个类,会报 java.lang.AbstractMethodError: javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V类似运行时异常。
  • 在运行期,很有可能出现依赖A在执行过程中调用C(1.0)以前有但是升级到C(1.1)就缺失的类c,导致运行期失败,出现很典型的依赖冲突时的NoClassDefFoundError错误。
  • 如果是升级后出现原有的方法被修改而不存在的情况时,就会抛出NoSuchMethodError错误。
  • 首先可以借助Maven查看依赖的依赖树来分析一下:手动:mvn dependency:tree,或者使用IDEA的Maven Helper插件Dependency Analyzer插件来可视化地分析依赖关系,或者 mvn dependency:tree -Dverbose查看依赖树。这个过程后可以明确哪些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>