maven传递依赖

Maven传递依赖

依赖的传递性。通过依赖设置解决了项目的CLASSPATH 问题,实际情况是我们依赖的项目其本身也是依赖其他的项目的,

如我依赖commons-email,而commons-email 需要依赖JavaMail 和JAF,这个时候,Maven 会自动处理这个依赖传递,会将JavaMail 和JAF 也会加入到CLASSPATH 中,通过这种传递地址,可以确保依赖的完整性,保证程序的正常运行。

 

maven会根据groupId和artifactId来进行依赖去重,maven最终只取一个artifact,去重多版本。(去重的依据:第一是路径最短优先,第二是声明优先),

 

如果App1依赖A,A依赖1.0 版本的F,App1 同时依赖B,B 依赖1.1 版本的F,App1 还依赖C,C 本身依赖D,D依赖1.2 版本的F,如下图:


maven传递依赖
 

那么App1 依赖哪个版本的F?

Maven在这里处理有两个机制,

第一是路径最短优先

第二是声明优先

假设我们将App1 设为根节点,那么F:1.0 距离根节点的路径为2,F:1.1也为2,F:1.2 为3,那么根据最短路径原则F:1.2 被淘汰。

在同为路径2 的F:1.0 和F1.1 之间根据声明优先原则,F:1.0是在A声明中引入的,而A 声明在先,那么F:1.0胜出,App1最终依赖的F 版本为1.0。

 

在pom.xml中dependency越下面,那么越先声明。

 

但是项目确实需要F:1.2,如何将F:1.2 加入到项目的CLASSPATH 中呢?

这里有两个方法:优先声明和依赖排除(Exclusion)。 

声明优先:

前面说到最短路径原则,如果我在App1的pom.xml声明之间依赖F:1.2,那么F:1.2与项目根节点的路径为1,而F:1.0 和F:1.1 的路径都为2,则F:1.2 胜出,项目依赖F:1.2。

依赖排除:

指在声明依赖时,指明排除对某一项目的依赖,如在依赖hibernate-core 3.3.1.GA 时,排除对slf4j-api(排除时需要指明groupId 和artifactId,不需要指明version),这样就可以断开依赖的链,依赖就不会传递下去。依赖排除声明如下:


maven传递依赖
 

回到App1 项目中,如果我们在声明A依赖时排除对F的依赖,声明B 时排除对F的依赖,那么D 依赖的F:1.2 就会胜出,项目就会依赖F:1.2 啦。 所以让App1 依赖F:1.2 的结构如下(声明优先和依赖排除选一即可):


maven传递依赖
 

说明一下,依赖去重是基于groupId和artifactId完全一致才生效的。(不需要version)

一个反面的例子,很多开发人员会问,我的WEB-INF/lib目录下怎么出现两个jdom.jar?一个是1.0的,一个1.1的。

这里说明一下: jdom 1.0的groupId 是jdom,而jdom 1.1的groupId是org.jdom,两者groupId 不一致(虽然artifactId 是一样的),无法使用依赖去重,

Maven认为这两个jar 包完全不相关,而不是一个artifact 的两个版本,所以这两个jar 包都出现在lib 目录下啦。

 

这种情况在开源项目中很常见:刚开始,一个程序员写了一个小项目,groupId直接为项目名称:com.xxx;后来越做越大,被Apache ASF 采纳,groupId 调整为org.apache.xxx;

最后觉得约束太大,又想单飞,做一个新的产品,如org.xxx。回顾这个产品,groupId 变了三次,如果设置不好,你的lib 目录下可能出现该项目的三个jar包,

iBATIS就是这个例子,groupId 分别是: com.ibatis -> org.apache.ibatis -> org.mybatis,这个一定要注意一下。

你可能感兴趣的:(maven传递依赖)