五、聚合與繼承

好久沒有更新了,在這里給大家說聲抱歉,實在是因為最近加班忙成狗,還有一個原因是我想把《maven實戰》這本書剩下的最后幾個章節看完在統一做筆記,所以......,好了閑話少許,現在開始我們今天的聚合與繼承章節的知識要點回顧

study.jpg

maven的聚合特性能夠把項目的各個模塊都聚合在一起構建,而maven的繼承特性則能夠幫助抽取各個模塊相同的依賴和插件等配置,從而讓項目像OPPO那樣從這一刻更清晰

聚合

聚合的目的是為了實現多個模塊同時構建,為了配置聚合,我們需要創建獨立的模塊,為模塊編寫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>

該項目只需要提供上面的pom.xml配置文件即可,其他src也不需要,這里的packaging必須為pom,否則無法構建
為了方便構建,通常將聚合模塊作為項目目錄的最頂層,其他被聚合的子模塊作為項目目錄的子目錄存在
maven在編譯時會根據pom.xml中配置的modules得出一個反應堆構建順序,并按照這個順序編譯項目模塊
建議我們在創建項目的時候為項目模塊提供一個合理的name,因為構建的結果中是通過各個模塊中配置的name來標識每一個項目模塊的構件狀態的
如下所示,是對一個account-parent項目的構件結果:

image.png

繼承

繼承目的是為了將一些公共的配置抽取出來,方便其他模塊共用,為了實現模塊繼承,需要以下幾步:

  1. 創建一個新的項目模塊,并配置其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

  1. 編寫其他子模塊引用父模塊
<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>

上面通過parent加入父模塊在maven倉庫中的坐標來引用maven
通過relativePath相對路徑的方式指定了父模塊基于當前子模塊的位置,maven在構建子模塊的時候就不會要求父模塊一定要先于安裝到本地倉庫,因為通過該標簽指定的相對路徑已經可以明確指定到父模塊,當然如果本地倉庫和relativePath所提供的路徑找不到父模塊,那么構建將會失敗

可繼承的pom元素

groupId: 項目組id,項目坐標核心元素
version: 項目版本,項目坐標核心元素
description: 項目描述信息
organization: 項目組織信息
inceptionYear: 創始年份
url: 項目地址,這里可以向項目的index連接
developers: 項目開發者信息
contributors: 項目貢獻者信息
distributionManagement: 項目的部署地址
issueManagement: 項目缺陷跟蹤信息
ciManagement: 項目持續集成的部署信息
scm: 項目的版本控制系統信息
mailingLists: 項目的郵件地址列表信息
properties: 自定義的maven屬性
dependencies: 項目依賴
dependencyMangement: 項目依賴管理配置
repositories: 項目倉庫
build: 項目源碼目錄配置、輸出目錄配置、插件配置、插件管理配置等
reporting: 項目的輸出目錄配置、報告插件配置等
通過build參數可以看到插件配置也可以被繼承

依賴管理

dependenciesdependencyManagement
在父模塊pom.xml中的dependencies中引入的依賴會被所有引用該父模塊的子模塊繼承,但并不是所有的子模塊都會用到父模塊中聲明的依賴,所以為了防止多余的依賴,父容器中可以通過dependencyManagement來聲明jar包依賴。
dependencyManagement中聲明的依賴配置會被子模塊繼承,但是不會被實際使用,除非子模塊顯示通過groupId:artifactId聲明需要引用該依賴
使用dependencyManagement的好處是可以在父模塊中對jar包版本進行統一管理,推薦這么做

import依賴范圍

在前面依賴范圍提到過import,它的作用只會對pom.xml中配置的dependencyManagement有效
import的作用是:將目標pom中的dependencyManagement配置導入并合并到當前pom.xml
import依賴范圍是除了使用代碼復制和繼承之外的又一個可以將外部配置導入的方式,下面是具體配置:
父項目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的子項目

<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 項目,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>
        <!-- 從繼承的父項目中繼承依賴 -->
        <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依賴范圍由于其特殊性,它的類型(type)一般都是pomscopeimport

插件管理

與依賴管理相似的是插件管理,maven中提供了plugins, pluginManagement兩個元素,這兩個元素的用途與依賴管理中的dependenciesdependencyManagement用法一致
這里不做贅述

聚合與繼承之間的關系

不同點:

  1. 聚合與繼承是兩個概念,其目的是完全不同的,聚合是為了解決多模塊同時構建的問題,而繼承則是為了解決多模塊重復配置問題
  2. 對于聚合模塊來說,它知道有哪些子模塊需要被聚合,(<modules>),而對于繼承來說它不知道有哪些子模塊繼承了它,但相反,子模塊知道他們繼承的是哪一個父模塊(<parent>)
    聚合模塊.png

    繼承模塊.png

    相同點:
    聚合與繼承模塊pom的類型(type)都是pom,他們都除了包含一個pom.xml文件之外,沒有其他東西
    推薦做法:為了方便,可以將聚合和繼承兩者合成一個模塊,在一個父模塊中配置聚合和繼承

約定優于配置

使用maven比使用ant配置更少,更方便,雖然用戶感覺上自己配置的東西少了,其實是maven內部將某一些配置提前預設好了,比如在超級pom中可以看到的:

  1. 源碼目錄為src/main/java
  2. 編譯輸出目錄為target/classes
  3. 打包方式為jar
  4. 包輸出目錄為target/
    所有項目的pom.xml都繼承與超級pom中的配置,超級pom具體位置在:
    ${MVN_HOME}/lib/maven-model-builder-x.x.x.jar/org/apache/maven/model/pom-4.0.0.xml

反應堆

對于單模塊反應堆就是它本身,但對于多個模塊項目來說,反應堆就包含了模塊之間繼承與依賴的關系
maven的實際構建順序是這樣形成的:

  1. maven按序讀取pom,如果該pom沒有依賴模塊,則直接進行構建
  2. 如果依賴了其他模塊,那么先構建其他模塊
  3. 遞歸1,2直到完成整個項目的構建工作
    特別說明,項目模塊之間的依賴配置,不能出現循環依賴的現象,也就是A依賴B,B也依賴于A,這樣的配置將會導致maven構建失敗

裁剪反應堆

對聚合模塊運行maven命令比如mvn clean installmaven會根據計算出來的反應堆順序將全部子模塊都構建完畢并安裝到本地倉庫,為了選擇性的構件某些模塊進行構建而不是將所有模塊進行構建,那么可以采用maven提供的幾條裁剪反應堆命令:
-am also make 構建模塊同時構建所列模塊依賴的其他模塊
-amd also make dependency構建模塊同時構建依賴當前模塊的其他模塊
-pl --projects 構建指定的模塊,多個模塊用,分隔
-rf resume-from 在計算出的反應堆順序基礎上,從指定模塊開始向后構建
下面是各個命令的實例:
假設存在account-parent,account-email,account-persist三個模塊,他們之間的關系如下:

模塊間依賴關系.png

-pl:構建指定模塊
mvn clean install -pl account-parent
將會構建account-parent模塊

-am:構建模塊并構建其依賴的其他模塊
mvn clean install -pl account-email -am
將會構建account-parent/account-email模塊

-amd: 構建模塊并構建依賴它的其他模塊
mvn clean install -pl account-parent -amd
將會構建account-parent/account-email/account-persist

-rf 指定構建的起始模塊,假設模塊依賴關系如下
account-parent
- account-email
- account-persist
mvn clean install -pl account-parent -amd -rf account-persist
將會構建account-parent/account-persist,而跳過account-email模塊的構建
好了,以上就是本章的重點知識,鍵盤敲到這里,再看看現在的時間0:39,再想到明天臺風天還要上班,趕緊洗干凈滾床上睡覺啦!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一、聚合 想要一次構建兩個項目,而不是到兩個模塊目錄下分別執行mvn命令。 為了能使用一條命令構建兩個模塊,需要創...
    JarvisTH閱讀 628評論 0 0
  • 何為Maven的聚合 假設有這么一個場景,有ABC三個項目,需要一次構建三個項目,而不是分別到每個項目下面執行mv...
    超級大雞腿閱讀 532評論 0 0
  • Maven的聚合特性能夠把項目的各個模塊聚合在一起構建,而繼承特性則能夠幫助抽取各模塊相同的依賴和插件等配置,在簡...
    洛楊凡閱讀 671評論 0 0
  • 那樣淡然微笑的女子,一直是心里的慰籍和向往。 此心安處是吾鄉。 面對迎面而來的氣運加諸于身的苦楚反復,苦難侮辱,以...
    銘玥詠全閱讀 198評論 0 2
  • 雨不大不小 剛剛好 不纏綿也不討人厭煩 兩條鐵軌正是我生活軌跡 一頭連著工作 一頭連著家 旅途行人不多不少 剛剛滿...
    躁動的青春閱讀 243評論 0 1