一:DependencyManagement / Dependencies的区别
dependencyManagement统一管理项目的版本号,只声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。在子项目中写了该依赖项,并且没有指定具体版本,会自动从父项目中继承该项,并且version和scope都读取自父pom; 另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
所有声明在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。一般webapp的pom不能直接写dependencies,需嵌套在dependencyManagement中。
二:3种特殊范围声明
compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-core,在编译,测试和运行的时候都需要使用该依赖。
provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于tomcat容器已经提供,就不需要Maven重复地引入一遍。
test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子就是JUnit,它只有在编译测试代码及运行测试的时候才需要。
例如:在dependencyManagement中声明:
三:依赖关系
1).短路优先:谁离得最近就使用谁的依赖jar包
C到达A为C->B->A
C到达B为C->B
例如:
A中的 commons-io的版本为2.4
B中的commons-io的版本为2.0
C中依赖于B,B依赖于A
则C的junit的包为2.0版本
因为依赖的短路优先
2).如果两条路都是一样长的时候呢?
C到达A为C->A
C到达B为C->B
则看pom文件中依赖的两个工程谁在前面就是用哪个版本。但不一定生效 , 往往是这种路径一致造成jar冲突。
fee-facade:关系图:可以看到引入了m-commons。
但是在webapp实际引用关系图中fee-facade下层并没有出现m-commons。
可以查一下m-commoms实际上在这被引用,是被bprod-facade带进来的。离根部距离为2,而fee-facade离根部距离为2,所以它的m-commms距离为3。所以根据就近原则。真实引用的为距离为2的m-commoms。
四:jar包冲突
如果项目同时依赖两个子项目的某个包,路径一样且版本号不一致。编译打包后target目录生成了2个不同版本的jar包。运行时候会报错。我们可以通过报错信息在依赖关系图中找到真实的引用。制定新版本或者把低版本的jar包exclude掉。