maven的依赖调解机制
本文目的
上一篇,maven项目的结构为什么是这样的。
每个 maven
项目中,会引用很多的第三方依赖,第三方依赖中可能又引用了其他的第三方,整个项目依赖分布图如下:
从上图可以看出来,一个项目引用的依赖分布图,非常的“凌乱”,有的依赖有多个依赖入口。
那就会有个问题,比如你自己依赖了gson
包,而依赖的其他第三方依赖中也引用了gson
,那项目最终会使用哪个?
本文就解释这块,maven是怎么做的,这个在maven里称为依赖调解
。以下内容参考学习《maven实战》。
正文
在说依赖调解
之前,首先要知道传递性依赖
,即在maven中强大的scope标签详解中提到的。A引用了B包,B包里又引用了C包,如果在合适的依赖范围scope控制下,A同时就拥有了C包
。
Maven
引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下,我们只需要关心项目的直接依赖是什么,而不需要考虑这些直接依赖会引入什么传递性依赖
。但有的时候,当传递性依赖
造成问题的时候,我们就需要清楚知道该传递性依赖
是从哪条依赖路径引入的。(比如:jar包冲突,引入了版本过低的jar包造成异常)。
1. 依赖调解
依赖调解
是maven
对于引用重复依赖的一种选择机制。它主要有几个原则。
1.1 路径最近者优先
比如下图:
当在我们的pom.xml
中存在两条路线对X(1.0)
包的依赖,maven
会遵循第一原则,路径最近者优先。从上图来看,优先采用下边A依赖-----X(1.0)
。
1.2 第一声明者优先
当然只看路径最近者优先这个原则,肯定还不够,因为有可能正好两条路线长度都一样长。maven
在2.0.9
版本之后,为了尽可能避免构建的不确定性,定义了第二个原则,第一声明者优先。
如下图所示:
当两条对于X(1.0)
、X(2.0)
两个版本的依赖路线长度相同,那因为D依赖
声明在A依赖
之前,因此优先引用的即D依赖
的X(1.0)
这条线。
2. 自定义排包
当然还有一种情况,如上图,存在X(1.0)
、X(2.0)
的两个依赖,但是因为遵循了第二原则,X(1.0)
会生效,但是我们又想使用X(2.0)
包,那就需要自己在pom
中,将第一条线里的X(1.0)
版本排除掉。这个使用到了<exclusions>
标签。举个栗子,如下:
<!-- mybatis -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
像上图的<exclusions>
排包写法,mybatis-plus-boot-starter
中排除掉对mybatis
包的依赖。
下一篇,maven项目打包构建的日志分析。