当A依赖B,B依赖C时,如果B中C的scope是provided或test,那么A不依赖C;否则A依赖C,scope与B中C的scope相同,这种行为就是依赖传递。此时,如果A也依赖C,那么A中不用声明对C的依赖,maven会自动处理项目之间的依赖关系。
可以通过mvn dependency:tree
命令查看工程的依赖树,比如:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ ProjectA --- [INFO] cn.timd:ProjectA:jar:1.0-SNAPSHOT [INFO] +- cn.timd:ProjectB:jar:1.0-SNAPSHOT:compile [INFO] | \- cn.timd:ProjectC:jar:1.0-SNAPSHOT:compile [INFO] \- junit:junit:jar:3.8.1:test
依赖冲突是指项目最终依赖相同artifact的多个版本。比如:A依赖B 和 C,B依赖E的1.0版本,C依赖D,D依赖E的2.0版本。此时A就依赖E的1.0和2.0版本。当发生依赖冲突时,maven使用“最近者获取策略”(nearest wins strategy),也就是最终会选择依赖树中离工程最近的那个版本。本例中,会选择1.0版本。
假设E的2.0版本中,新增了sayWorld功能,并且在A中,使用到了sayWorld功能,那么就会引起NoSuchMethodError、ClassNotFoundException等问题。
1,可选依赖
A依赖B,B依赖C,如果B中标记C为optional,那么A不依赖C。比如:
<dependency> <groupId>cn.timd</groupId> <artifactId>ProjectC</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> <optional>true</optional> </dependency>
比如在上面的例子中,可以在B中将E标记位optional,来保证A依赖2.0版本的E
2,排除依赖
A依赖B,B依赖C,可以在A中声明对B的依赖的时候,同时排除(由B引入的)对C的依赖。比如:
<dependency> <groupId>cn.timd</groupId> <artifactId>ProjectB</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>cn.timd</groupId> <artifactId>ProjectC</artifactId> </exclusion> </exclusions> </dependency>
比如在上面的例子中,可以在A中声明对B的依赖的时候,排除由B引入的对E 1.0的依赖,来保证A依赖2.0版本的E
3,直接修改项目依赖
上面的例子中,E 2.0之所以没被maven选择,是因为它离A比较远,那么可以直接把E 2.0加入到A的dependencies中,来解决依赖冲突的问题。