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插件,如下图,可以清晰的看到依赖树,进而决定如何解决
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)
<scope>system</scope>
有以下参数
- compile: 编译依赖范围(默认)
- test: 测试依赖范围 典型例子是JUnit,它只有在编译测试代码及运行测试的时候才需要
- provided: 已提供依赖范围
使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。
典型例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍。 - runtime: 运行时依赖范围。
使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。
典型例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
排除依赖(Excluded dependencies)
排除不需要从所依赖的项目中传递过来的依赖 <exclude/>
可选依赖(Optional dependencies)
被依赖的项目主动不把可以传递的依赖传递下去
解决方法
使用Maven提供的Optional和Exclusions来控制依赖的传递
Optional 定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖才行。
A
-> B
D
-> A
-> B
A/pom.xml如下:
<dependency>
<groupId>com.zxa</groupId>
<artifactId>B</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
这种情况下,此项目对B的依赖将不会传递给D
Exclusions 则是主动排除子项目传递过来的依赖。
<dependency>
<groupId>com.bar</groupId>
<artifactId>A</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>com.bar</groupId>
<artifactId>B</artifactId>
</exclusion>
</exclusions>
</dependency>
A