maven jar包冲突原理与解决办法

jar 包冲突原因

Caused by:java.lang.NoSuchMethodError
Caused by: java.lang.ClassNotFoundException

大概就是jar包冲突(今天遇到的是第一种)

依赖传递

 A依赖
            -> B
 D依赖
      -> A
      -> B

因为Maven拥有传递依赖的特性,因此真实的依赖树是:

A依赖
      -> B

  D依赖
      -> A
          -> B
      -> B

依赖传递问题:

  • 当依赖层级很深的时候,可能造成循环依赖(cyclic dependency)
  • 当依赖的数量很多的时候,依赖树会非常大

查找依赖冲突

idea插件 dependency analyzer插件,如下图,可以清晰的看到依赖树,进而决定如何解决


image.png

maven提供的解决方法:

依赖调节--就近原则

例如:
A项目通过依赖传递依赖了两个版本的D:
A -> B -> C -> ( D 2.0) , A -> E -> (D 1.0)
那么最终A依赖的D的version将会是1.0,因为1.0对应的层级更少,也就是更近。

依赖管理

Dependency management,可以大大简化子POM的依赖声明。
即父pom.xml声明版本,子pom.xml
不用指定版本号。

  • 依赖范围(Dependency scope)
     system

有以下参数

  • compile: 编译依赖范围(默认)
  • test: 测试依赖范围 典型例子是JUnit,它只有在编译测试代码及运行测试的时候才需要
  • provided: 已提供依赖范围
    使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。
    典型例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍。
  • runtime: 运行时依赖范围。
    使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。
    典型例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。

排除依赖(Excluded dependencies)

排除不需要从所依赖的项目中传递过来的依赖

可选依赖(Optional dependencies)

被依赖的项目主动不把可以传递的依赖传递下去

解决方法

使用Maven提供的Optional和Exclusions来控制依赖的传递
Optional 定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖才行。

A
  -> B
D
  -> A
  -> B

A/pom.xml如下:


    com.zxa
    B
    1.0
    true

这种情况下,此项目对B的依赖将不会传递给D
Exclusions 则是主动排除子项目传递过来的依赖。


    com.bar
    A
    1.0
    
        
            com.bar
            B
        
    

A

你可能感兴趣的:(maven jar包冲突原理与解决办法)