好久沒(méi)有更新了,在這里給大家說(shuō)聲抱歉,實(shí)在是因?yàn)樽罱影嗝Τ晒?,還有一個(gè)原因是我想把《maven實(shí)戰(zhàn)》這本書(shū)剩下的最后幾個(gè)章節(jié)看完在統(tǒng)一做筆記,所以......,好了閑話(huà)少許,現(xiàn)在開(kāi)始我們今天的聚合與繼承章節(jié)的知識(shí)要點(diǎn)回顧

maven的聚合特性能夠把項(xiàng)目的各個(gè)模塊都聚合在一起構(gòu)建,而maven的繼承特性則能夠幫助抽取各個(gè)模塊相同的依賴(lài)和插件等配置,從而讓項(xiàng)目像OPPO那樣從這一刻更清晰
聚合
聚合的目的是為了實(shí)現(xiàn)多個(gè)模塊同時(shí)構(gòu)建,為了配置聚合,我們需要?jiǎng)?chuàng)建獨(dú)立的模塊,為模塊編寫(xiě)pom.xml作為聚合模塊
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>parent project name</name>
<modules>
<module>module1-artifactId</module>
<module>module2-artifactId</module>
</modules>
</project>
該項(xiàng)目只需要提供上面的pom.xml配置文件即可,其他src也不需要,這里的packaging必須為pom,否則無(wú)法構(gòu)建
為了方便構(gòu)建,通常將聚合模塊作為項(xiàng)目目錄的最頂層,其他被聚合的子模塊作為項(xiàng)目目錄的子目錄存在
maven在編譯時(shí)會(huì)根據(jù)pom.xml中配置的modules得出一個(gè)反應(yīng)堆構(gòu)建順序,并按照這個(gè)順序編譯項(xiàng)目模塊
建議我們?cè)趧?chuàng)建項(xiàng)目的時(shí)候?yàn)轫?xiàng)目模塊提供一個(gè)合理的name,因?yàn)闃?gòu)建的結(jié)果中是通過(guò)各個(gè)模塊中配置的name來(lái)標(biāo)識(shí)每一個(gè)項(xiàng)目模塊的構(gòu)件狀態(tài)的
如下所示,是對(duì)一個(gè)account-parent項(xiàng)目的構(gòu)件結(jié)果:

繼承
繼承目的是為了將一些公共的配置抽取出來(lái),方便其他模塊共用,為了實(shí)現(xiàn)模塊繼承,需要以下幾步:
- 創(chuàng)建一個(gè)新的項(xiàng)目模塊,并配置其pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>parent project name</name>
</project>
跟聚合一樣,父模塊中的packaging也必須要求是pom
- 編寫(xiě)其他子模塊引用父模塊
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../account-parent/pom.xml</relativePath>
</parent>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>parent project name</name>
</project>
上面通過(guò)parent加入父模塊在maven倉(cāng)庫(kù)中的坐標(biāo)來(lái)引用maven
通過(guò)relativePath相對(duì)路徑的方式指定了父模塊基于當(dāng)前子模塊的位置,maven在構(gòu)建子模塊的時(shí)候就不會(huì)要求父模塊一定要先于安裝到本地倉(cāng)庫(kù),因?yàn)橥ㄟ^(guò)該標(biāo)簽指定的相對(duì)路徑已經(jīng)可以明確指定到父模塊,當(dāng)然如果本地倉(cāng)庫(kù)和relativePath所提供的路徑找不到父模塊,那么構(gòu)建將會(huì)失敗
可繼承的pom元素
groupId: 項(xiàng)目組id,項(xiàng)目坐標(biāo)核心元素
version: 項(xiàng)目版本,項(xiàng)目坐標(biāo)核心元素
description: 項(xiàng)目描述信息
organization: 項(xiàng)目組織信息
inceptionYear: 創(chuàng)始年份
url: 項(xiàng)目地址,這里可以向項(xiàng)目的index連接
developers: 項(xiàng)目開(kāi)發(fā)者信息
contributors: 項(xiàng)目貢獻(xiàn)者信息
distributionManagement: 項(xiàng)目的部署地址
issueManagement: 項(xiàng)目缺陷跟蹤信息
ciManagement: 項(xiàng)目持續(xù)集成的部署信息
scm: 項(xiàng)目的版本控制系統(tǒng)信息
mailingLists: 項(xiàng)目的郵件地址列表信息
properties: 自定義的maven屬性
dependencies: 項(xiàng)目依賴(lài)
dependencyMangement: 項(xiàng)目依賴(lài)管理配置
repositories: 項(xiàng)目倉(cāng)庫(kù)
build: 項(xiàng)目源碼目錄配置、輸出目錄配置、插件配置、插件管理配置等
reporting: 項(xiàng)目的輸出目錄配置、報(bào)告插件配置等
通過(guò)build參數(shù)可以看到插件配置也可以被繼承
依賴(lài)管理
dependencies與dependencyManagement
在父模塊pom.xml中的dependencies中引入的依賴(lài)會(huì)被所有引用該父模塊的子模塊繼承,但并不是所有的子模塊都會(huì)用到父模塊中聲明的依賴(lài),所以為了防止多余的依賴(lài),父容器中可以通過(guò)dependencyManagement來(lái)聲明jar包依賴(lài)。
dependencyManagement中聲明的依賴(lài)配置會(huì)被子模塊繼承,但是不會(huì)被實(shí)際使用,除非子模塊顯示通過(guò)groupId:artifactId聲明需要引用該依賴(lài)
使用dependencyManagement的好處是可以在父模塊中對(duì)jar包版本進(jìn)行統(tǒng)一管理,推薦這么做
import依賴(lài)范圍
在前面依賴(lài)范圍提到過(guò)import,它的作用只會(huì)對(duì)pom.xml中配置的dependencyManagement有效
import的作用是:將目標(biāo)pom中的dependencyManagement配置導(dǎo)入并合并到當(dāng)前pom.xml中
import依賴(lài)范圍是除了使用代碼復(fù)制和繼承之外的又一個(gè)可以將外部配置導(dǎo)入的方式,下面是具體配置:
父項(xiàng)目b
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cbm.stu</groupId>
<artifactId>maven-parent-b</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>maven-parent-b</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
繼承b的子項(xiàng)目
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cbm.stu</groupId>
<artifactId>maven-study-mail</artifactId>
<version>2.1</version>
<packaging>jar</packaging>
<name>maven-study-mail</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<!-- 此處繼承b 項(xiàng)目,type為pom,scope 為 import -->
<dependency>
<groupId>com.cbm.stu</groupId>
<artifactId>maven-parent-b</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 從繼承的父項(xiàng)目中繼承依賴(lài) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
import依賴(lài)范圍由于其特殊性,它的類(lèi)型(type)一般都是pom,scope為import
插件管理
與依賴(lài)管理相似的是插件管理,maven中提供了plugins, pluginManagement兩個(gè)元素,這兩個(gè)元素的用途與依賴(lài)管理中的dependencies和dependencyManagement用法一致
這里不做贅述
聚合與繼承之間的關(guān)系
不同點(diǎn):
- 聚合與繼承是兩個(gè)概念,其目的是完全不同的,聚合是為了解決多模塊同時(shí)構(gòu)建的問(wèn)題,而繼承則是為了解決多模塊重復(fù)配置問(wèn)題
- 對(duì)于聚合模塊來(lái)說(shuō),它知道有哪些子模塊需要被聚合,(<
modules>),而對(duì)于繼承來(lái)說(shuō)它不知道有哪些子模塊繼承了它,但相反,子模塊知道他們繼承的是哪一個(gè)父模塊(<parent>)
聚合模塊.png
繼承模塊.png
相同點(diǎn):
聚合與繼承模塊pom的類(lèi)型(type)都是pom,他們都除了包含一個(gè)pom.xml文件之外,沒(méi)有其他東西
推薦做法:為了方便,可以將聚合和繼承兩者合成一個(gè)模塊,在一個(gè)父模塊中配置聚合和繼承
約定優(yōu)于配置
使用maven比使用ant配置更少,更方便,雖然用戶(hù)感覺(jué)上自己配置的東西少了,其實(shí)是maven內(nèi)部將某一些配置提前預(yù)設(shè)好了,比如在超級(jí)pom中可以看到的:
- 源碼目錄為
src/main/java - 編譯輸出目錄為
target/classes - 打包方式為
jar - 包輸出目錄為
target/
所有項(xiàng)目的pom.xml都繼承與超級(jí)pom中的配置,超級(jí)pom具體位置在:
${MVN_HOME}/lib/maven-model-builder-x.x.x.jar/org/apache/maven/model/pom-4.0.0.xml
反應(yīng)堆
對(duì)于單模塊,反應(yīng)堆就是它本身,但對(duì)于多個(gè)模塊項(xiàng)目來(lái)說(shuō),反應(yīng)堆就包含了模塊之間繼承與依賴(lài)的關(guān)系
maven的實(shí)際構(gòu)建順序是這樣形成的:
-
maven按序讀取pom,如果該pom沒(méi)有依賴(lài)模塊,則直接進(jìn)行構(gòu)建 - 如果依賴(lài)了其他模塊,那么先構(gòu)建其他模塊
- 遞歸1,2直到完成整個(gè)項(xiàng)目的構(gòu)建工作
特別說(shuō)明,項(xiàng)目模塊之間的依賴(lài)配置,不能出現(xiàn)循環(huán)依賴(lài)的現(xiàn)象,也就是A依賴(lài)B,B也依賴(lài)于A,這樣的配置將會(huì)導(dǎo)致maven構(gòu)建失敗
裁剪反應(yīng)堆
對(duì)聚合模塊運(yùn)行maven命令比如mvn clean install,maven會(huì)根據(jù)計(jì)算出來(lái)的反應(yīng)堆順序?qū)⑷孔幽K都構(gòu)建完畢并安裝到本地倉(cāng)庫(kù),為了選擇性的構(gòu)件某些模塊進(jìn)行構(gòu)建而不是將所有模塊進(jìn)行構(gòu)建,那么可以采用maven提供的幾條裁剪反應(yīng)堆命令:
-am also make 構(gòu)建模塊同時(shí)構(gòu)建所列模塊依賴(lài)的其他模塊
-amd also make dependency構(gòu)建模塊同時(shí)構(gòu)建依賴(lài)當(dāng)前模塊的其他模塊
-pl --projects 構(gòu)建指定的模塊,多個(gè)模塊用,分隔
-rf resume-from 在計(jì)算出的反應(yīng)堆順序基礎(chǔ)上,從指定模塊開(kāi)始向后構(gòu)建
下面是各個(gè)命令的實(shí)例:
假設(shè)存在account-parent,account-email,account-persist三個(gè)模塊,他們之間的關(guān)系如下:

-pl:構(gòu)建指定模塊mvn clean install -pl account-parent將會(huì)構(gòu)建
account-parent模塊
-am:構(gòu)建模塊并構(gòu)建其依賴(lài)的其他模塊
mvn clean install -pl account-email -am
將會(huì)構(gòu)建account-parent/account-email模塊
-amd: 構(gòu)建模塊并構(gòu)建依賴(lài)它的其他模塊
mvn clean install -pl account-parent -amd
將會(huì)構(gòu)建account-parent/account-email/account-persist
-rf 指定構(gòu)建的起始模塊,假設(shè)模塊依賴(lài)關(guān)系如下
account-parent
- account-email
- account-persist
mvn clean install -pl account-parent -amd -rf account-persist
將會(huì)構(gòu)建account-parent/account-persist,而跳過(guò)account-email模塊的構(gòu)建
好了,以上就是本章的重點(diǎn)知識(shí),鍵盤(pán)敲到這里,再看看現(xiàn)在的時(shí)間0:39,再想到明天臺(tái)風(fēng)天還要上班,趕緊洗干凈滾床上睡覺(jué)啦?。?!

