一般Java开发过程中,包冲突异常提现在下面几个

  1. AbstractMethodError
  2. NoClassDefFoundError
  3. ClassNotFoundException
  4. LinkageError

java 冲突 日志jar java包冲突_spring

像上图,就发生了包引用冲突,如果C包v0.1版本在前,JVM加载过v0.1版本里的同名类后就不会加载v0.2里的同名类,这很可能造成丢失了v0.2里同类里新增的方法属性等等。

接下来我们看看Maven对这种情况是如何进行管理的。

Maven 对 pom 文件的传递性依赖自动进行管理, 其中有一个原则 绝对不允许最终的classpath出现同名不同版本的jar包

java 冲突 日志jar java包冲突_java 冲突 日志jar_02

Maven会根据pom文件中的groupId、artifactId、version来判断jar是否冲突,这就是规范约定的好处之一。

如果出现了同名不同版本的jar包,Maven的处理原则是 离你项目更近的jar包会被选中,其他的淘汰 , 这句话什么意思呢 请看下图:

java 冲突 日志jar java包冲突_spring_03

C包V0.2胜出,因为它离我们的项目更近,看图应该就感觉很直观啦,

最终的classpath就是 A包、B包、D包、C包v0.2, Maven将C包v0.1排除掉啦。

Maven如何查看jar包依赖的jar

  1. 使用idea左侧的Maven工具栏,点击关心的jar包展开下面依赖的jar就好。

java 冲突 日志jar java包冲突_java 冲突 日志jar_04

  1. 使用 mvn dependency:tree

java 冲突 日志jar java包冲突_spring_05

使用 mvn dependency:tree -Dverbose -Dincludes=groupId:artifactId 可以列举出自己只关心的jar包, 例如我只关心org.springframework.boot:spring-boot-starter-json这个jar就使用后面这个命令: mvn dependency:tree -Dverbose -Dincludes=org.springframework.boot:spring-boot-starter-json

java 冲突 日志jar java包冲突_jar_06

也可以把结果输出到一个文件里打开查看: mvn dependency:tree -Dverbose -Dincludes=org.springframework.boot:spring-boot-starter-json > a.txt

java 冲突 日志jar java包冲突_jar包_07

手动处理包冲突

上面我们知道了Maven帮我们自动处理冲突采用的是就近原则,但这样并不保险,

有的时候万一最近的包是低版本的,这时候就会出现问题,

这时候工具做不了的事情就得我们人工手动来干预了,手动解决冲突有两种办法:

  1. 将需要的jar包直接写入到自己项目中的pom文件里去,这样根据Maven就近原则,即使其他的jar依赖了相同jar不同版本的,Maven也不会再采用。
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.4.RELEASE</version>
 </dependency>
  1. 使用Maven的exclusion,直接把其他包里的依赖排除掉,保留一个自己需要的就行。
<dependency>
    <groupId>com.xxx.xxx</groupId>
    <artifactId>xxxx-common</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </exclusion>
    </exclusions>
    <version>2.0-SNAPSHOT</version>
</dependency>
  1. 使用Idea插件 Maven Helper

这个插件可以很方便的分析出来有冲突的jar包,并且可以点击进行排除等处理,

具体查看官方文档 https://plugins.jetbrains.com/plugin/7179-maven-helper/ 。

最后一个问题

java 冲突 日志jar java包冲突_spring_08

如上图,C包1和2的版本感觉距离是一样的呀,那么Maven会排除哪一个呢?

答案是保留v0.1,如果距离一样,那么谁先声明就先保留谁,A包比D包先声明,所以保留A包的引用依赖。