第八章 聚合与继承

一、聚合

想要一次构建两个项目,而不是到两个模块目录下分别执行mvn命令。

为了能使用一条命令构建两个模块,需要创建一个额外的模块account-aggregator,然后通过该模块构建整个项目的所有模块。这个account-aggregator模块作为一个Maven项目,有自己的POM,同时作为聚合项目,又有特殊点:

<project xmlns="...">
    <modeVersion>4.0.0</modeVersion>
    <groupId>xxx.xxx.xxx</groupId>
    <artifactId>account-aggregator</artifactId>
    <version>1.1.0-snapshot</version>
    <packaging>pom</packaging>
    <name>xxx xxx</name>
    <modules>
        <module>account-email</module>
        <module>account-persist</module>
    </modules>
/project>

特殊的地方之一为packaging,值为pom。对于聚合模块来说,其打包发送packaging值必须为pom,否则无法构建。

元素modules,是实现聚合的最核心的配置。可以通过在一个打包发送为pom的Maven项目中声明容易数量的module元素来实现聚合模块。每个module的值都是一个当前POM的相对目录。

一般来说,为了方便快速定位内容,模块所处目录名称应当与其artifactId一致,不过这不是Maven的要求。

为了方便构建项目,通常将聚合模块放在项目目录的最顶层,其他模块则作为聚合模块的子目录存在。不一定要是父子关系,可以是平行目录。

如果使用平行目录结构,聚合模块的POM需要修改,指向正确的目录:

<modules>
    <module>../account-email</module>
    <module>../account-persist</module>
</modules>

聚合模块仅有一个pom.xml文件,仅仅帮助聚合其他模块构建。最后在聚合模块运行mvn clean install命令。

Maven首先解析聚合模块的POM、分析要构建的模块、计算出一个反应堆构建顺序,然后根据这个顺序依次构建各个模块。

在POM中配置合理的name字段,目的是让Maven构建输出更清晰。

二、继承

抽取重复的配置。需要创建POM的父子结构,然后在父POM中声明一些配置供子POM继承,实现“一处声明,多处使用”。

继续以上面的为基础,在account-aggregator下创建一个名为account-parent的子目录,然后在该目录下建立一个除account-aggregator之外的父模块。为此,在该子目录建一个pom.xml文件:

<project xmlns="...">
    <modelVersion>4.0.0</modulVersion>
    <groupId>xxx.xxx.xxx</groupId>
    <artifactId>acount-parent</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <name>Account Parent</name>
</project>

它使用和其他模块一致的groupId和version,使用artifactId为account-parent表示父模块。packaging为pom。不包含除POM以外的文件。

父模块需要其他模块继承。修改子模块的POM:

...
<parent>
    <groupId>xxx.xxx.xxx</groupId>
    <artifactId>account-parent</artifactId>
    <version>1.0.0-snapshot</version>
    <relativePath>../account-parent/pom.xml</relativePath>
</parent>
...

使用parent元素声明父模块,parent下的groupId、artifactId和version指定父模块坐标。relativePath元素表示父模块POM的相对路径。当项目构建时,Maven会根据relativePath检查父POM,如果找不到,再从本地仓库找。默认值是../pom.xml,即默认父POM在上层目录下。

更新过的POM没有为account-email声明groupId和version,这个子模块隐式的从父模块继承了这两个元素。子类也可以显示声明该两个元素不同的值。对于artifactId元素,子模块应该显式声明。

可继承的POM元素


依赖管理

Maven提供的dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活。在dependencyManagement下的依赖声明不会引入实际的依赖,不过能约束dependencies下的依赖使用。在account-parent中加入该配置:

...
<properties>
    <springframework.version>2.5.6</springframework>
    <junit.version>4.7</junit.version>
</properties>
<dependencyManagement>
    <dependencies>
        ...
    </dependencies>
 </dependencyManagement>
...

这段配置会被继承。修改account-email的POM:

<propeties>
    ...
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
     </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
     </dependency>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
     </dependency>
     <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
     </dependency>
    ...
</dependencies>

所有的springframework依赖只配置了groupId和artifactId,junit省去了version和scope。原因是继承了父pom的dependencyManagement配置。

如果子模块不声明依赖的使用,即使父POM声明了该依赖,也不会产生实际效果。

import范围依赖,该依赖只中dependencyManagement元素下才有效,使用该范围的依赖通常指向一个POM,作用是将目标POM中的dependencyManagement配置导入并合并到当前POM的dependencyManagement中。

<dependencyManagement>
    <dependencies>
        <dependency>
            ...
            <type>pom</type>
            <scpoe>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

插件管理

提供pluginManagement元素管理插件。在该元素配置的插件不会造成实际插件调用,当pom中配置了真正的plugin元素,并且其groupId和artifactId与该元素中配置的插件匹配时,该元素配置才会影响实际插件效果。

如果子模块不需要使用父模块中pluginManagement配置的插件,可以忽略。需要配置不同插件,可以自行配置覆盖父模块配置。

四、聚合与继承关系

聚合目的是为了方便快速构建项目,继承为了消除重复配置。

聚合与继承的父模块的POM的packaging必须是pom;聚合模块和继承关系的父模块只有POM。

五、约定优于配置

约定可以大量减少配置。Maven假设目录:

  • 源码目录:src/main/java
  • 编译输出目录:target/classes/
  • 打包方式:jar
  • 包输出目录:target/

Maven允许自定义源码目录,除非特殊情况,不建议这样做。

Maven设定核心插件原因是防止由于插件版本的变化而造成构建不稳定。

六、反应堆

在一个多模块的Maven项目中,反应堆(Reactor)指所有模块组成的一个构建结构。对于单模块项目,反应堆就是本身,对于多模块项目,反应堆包含各模块间的继承和依赖关系,从而能计算出合理的模块构建顺序。

1.反应堆构建顺序

修改account-aggregator聚合配置如下:

<module>
    <module>account-email</module>
    <module>account-persist</module>
    <module>account-parent</module>
</modules>

POM的读取次序不足以决定反应堆构建顺序,要考虑模块间的依赖和继承关系。



实际的构建顺序是:Maven按序读取POM,如果该POM没有依赖模块,那么构建该模块,否则先构建其依赖模块,如果该依赖还依赖于其他模块,则进一步构建依赖的依赖。

2.裁剪反应堆

Maven提供命令行选项裁剪反应堆,mvn-h可以看到这些选项:



在-pl -am或者-pl -amd基础上,还能应用-rf参数,以对裁剪后的反应堆再次裁剪。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容

  • 好久没有更新了,在这里给大家说声抱歉,实在是因为最近加班忙成狗,还有一个原因是我想把《maven实战》这本书剩下的...
    小炼君阅读 1,448评论 0 51
  • 一、聚合 为了能够使用一条命令就能构建 account-email和 account-persist两个模块,我们...
    madfrog_hc阅读 382评论 0 1
  • Maven的聚合特性能够把项目的各个模块聚合在一起构建,而继承特性则能够帮助抽取各模块相同的依赖和插件等配置,在简...
    洛杨凡阅读 652评论 0 0
  • 那是我小时候,一天星期五放晚学,我迈着轻快的步伐,蹦蹦跳跳地向家中跑去。 我一回到家就把书包扔到地上,...
    吴苗伊阅读 182评论 0 0
  • 用户行为,数据隐私和广告定向:eMarketer对FB剑桥分析事件的影响解读 要点速览: 用户行为:丑闻发生后,F...
    广告行业动态BAP阅读 470评论 0 0