首页 » Maven实战 » Maven实战全文在线阅读

《Maven实战》8.3.3 依赖管理

关灯直达底部

上一节的可继承元素列表包含了dependencies元素,说明依赖是会被继承的,这时我们就会很容易想到将这一特性应用到account-parent中。子模块account-email和account-persist同时依赖了org.springframework:spring-core:2.5.6、org.springframework:spring-beans:2.5.6、org.springframework:spring-context:2.5.6和junit:junit:4.7,因此可以将这些依赖配置放到父模块account-parent中,两个子模块就能移除这些依赖,简化配置。

上述做法是可行的,但却存在问题。到目前为止,我们能够确定这两个子模块都包含那四个依赖,不过我们无法确定将来添加的子模块就一定需要这四个依赖。假设将来项目中需要加入一个account-util模块,该模块只是提供一些简单的帮助工具,与springframework完全无关,难道也让它依赖spring-core、spring-beans和spring-context吗?那显然是不合理的。

Maven提供的dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。在dependencyManagement元素下的依赖声明不会引入实际的依赖,不过它能够约束dependencies下的依赖使用。例如,可以在account-parent中加入这样的dependencyManagement配置,见代码清单8-14。

代码清单8-14 在account-parent中配置dependencyManagement元素

首先该父POM使用了5.9.2节介绍的方法,将springframework和junit依赖的版本以Maven变量的形式提取了出来,不仅消除了一些重复,也使得各依赖的版本处于更加明显的位置。

这里使用dependencyManagement声明的依赖既不会给account-parent引入依赖,也不会给它的子模块引入依赖,不过这段配置是会被继承的。现在修改account-email的POM如下,见代码清单8-15。

代码清单8-15 继承了dependencyManagement的account-email POM

上述POM中的依赖配置较原来简单了一些,所有的springframework依赖只配置了groupId和artifactId,省去了version,而junit依赖不仅省去了version,还省去了依赖范围scope。这些信息可以省略是因为account-email继承了account-parent中的dependencyManagement配置,完整的依赖声明已经包含在父POM中,子模块只需要配置简单的groupId和artifactId就能获得对应的依赖信息,从而引入正确的依赖。

使用这种依赖管理机制似乎不能减少太多的POM配置,不过笔者还是强烈推荐采用这种方法。其主要原因在于在父POM中使用dependencyManagement声明依赖能够统一项目范围中依赖的版本,当依赖版本在父POM中声明之后,子模块在使用依赖的时候就无须声明版本,也就不会发生多个子模块使用依赖版本不一致的情况。这可以帮助降低依赖冲突的几率。

如果子模块不声明依赖的使用,即使该依赖已经在父POM的dependencyManagement中声明了,也不会产生任何实际的效果,如account-persist的POM,见代码清单8-16。

代码清单8-16 继承了dependencyManagement的account-persist POM

这里没有声明spring-context-support,那么该依赖就不会被引入。这正是dependencyManagement的灵活性所在。

5.5节在介绍依赖范围的时候提到了名为import的依赖范围,推迟到现在介绍是因为该范围的依赖只在dependencyManagement元素下才有效果,使用该范围的依赖通常指向一个POM,作用是将目标POM中的dependencyManagement配置导入并合并到当前POM的dependencyManagement元素中。例如想要在另外一个模块中使用与代码清单8-14完全一样的dependencyManagement配置,除了复制配置或者继承这两种方式之外,还可以使用import范围依赖将这一配置导入,见代码清单8-17。

代码清单8-17 使用import范围依赖导入依赖管理配置

注意,上述代码中依赖的type值为pom,import范围依赖由于其特殊性,一般都是指向打包类型为pom的模块。如果有多个项目,它们使用的依赖版本都是一致的,则就可以定义一个使用dependencyManagement专门管理依赖的POM,然后在各个项目中导入这些依赖管理配置。