maven 模块聚合与继承

在开发中,出于分工和设计和管理上的原因,我们无可避免地要进行分模块开发。
虽然OSGi、Jigsaw都有涉及到模块化,但常见的应用中,我们会使用一些构建工具(如maven)进行模块的管理。

模块

举个例子(示例代码),假设有两个模块:
user-model,用来定义用户的领域对象;
user-service,用来定义用户相关的业务操作,并依赖user-model模块。

如今我们需要构建这个项目,如果没有模块之间没有关联,可能需要cd到每个模块,进行mvn package,build我们想要的模块。
而且这些依赖模块代码若有更新,手工去重新build,明显是不现实的。

为了解决这个痛点,maven为我们提供了聚合模块的功能。

在maven中,我们只需要:

1. 定义一个 pom packaging类型的module

模块暂且称为user-aggregator
并在user-aggregator/pom.xml中定义其他模块成员的信息(<modules>)。

<groupId>org.niko.blog.demo.aggregator</groupId>
<artifactId>user-aggregator</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
...
<modules>
<module>user-model</module>
<module>../user-service</module>
</modules>

说明一下,maven 的聚合模块可以使用两种结构:

- 父子结构  
| aggregator
|-- son1
|-- son2

- 平行结构
|--aggregator
|--son1
|--son2

然而像上面那样混合使用也是可以的,目录结构类似下面:

个人经验来说,平行结构的一个好处就是,当你的不同模块在不同git仓库时,平行模块会比较适合。
即son1和son2是两个git仓库,这时候平行结构可以使其互不影响,这种场景在开发中还是经常会有的。

2. 子项目增加parent的声明:

user-model/pom.xml 模块:

<parent>
<groupId>org.niko.blog.demo.aggregator</groupId>
<artifactId>user-aggregator</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

user-service/pom.xml 模块:

<parent>
<groupId>org.niko.blog.demo.aggregator</groupId>
<artifactId>user-aggregator</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../user-aggregator/pom.xml</relativePath>
</parent>

3. 构建所有模块

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] user-aggregator
[INFO] user-model
[INFO] user-service
...
...
[INFO] Reactor Summary:
[INFO]
[INFO] user-aggregator ................................... SUCCESS [3.804s]
[INFO] user-model ........................................ SUCCESS [33.208s]
[INFO] user-service ...................................... SUCCESS [2.032s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Reactor 反应堆


细心的童鞋已经发现,上面一次构建的输出信息中有Reactor Build Order这几个单词,那这又是什么东西呢?
翻译过来就是反应堆,顾名思义,表示所有模块组成的一个构建集合(一个模块可以看做一个反应堆)。
不过反应堆还包含了模块间的依赖和继承,并会计算出构建顺序。

裁剪反应堆

上面的操作,是构建所有模块。那如果现在我想只构建某个模块(不构建没用到的模块)呢?这时就应该裁剪反应堆了。

具体使用

<!--
Maven 3.2.1 has added this feature, you can use -pl ! for exclude certain modules. This can be comma separated list of values that you want to include/exclude, exc
-->

假设user-service依赖user-model,现在使用裁剪反应堆来构建user-service,user-model也会被自动构建:

/.../user-aggregator/$ `mvn clean package -pl ../user-service -am`

参数说明:

Options:
-amd,--also-make-dependents:构建依赖于指定模块的模块
-rf,--resume-from:从构建顺序的某个模块开始构建
-pl,--projects: 构建指定的模块,模块间用逗号分割
-am,--also-make : 同时构健模块的所依赖的模块

好处


从上面介绍可以发现,使用聚合模块和继承有以下好处:

  1. 配置重用(继承);
  2. 依赖和插件统一管理,如dependencyManagement和pluginManagement;
  3. 自动分析和构建依赖,而且方便自身项目的version管理。

参考资料


【1】https://maven.apache.org/guides/mini/guide-multiple-modules.html
【2】Maven实战.徐晓斌