1. 程式人生 > >Maven中的聚合與繼承

Maven中的聚合與繼承

1、聚合

  一個帶有模組的專案稱為“多模組”或“聚合器”專案。模組是POM列出的專案,並作為一個組執行。一個pom打包的專案可以通過將它們作為模組來聚合一組專案的構建,這些模組是這些專案的目錄或pom檔案的相對路徑。

<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
                      https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>4.0.0</modelVersion> <groupId>org.codehaus.mojo</groupId> <artifactId>my-parent</artifactId> <version>2.0</version> <packaging>pom</packaging> <modules> <module>my-project</module> <module
>
another-project</module> <module>third-project/pom-example.xml</module> </modules> </project>

  在列出模組時,您不需要考慮模組間的依賴關係,也就是說,POM給出的模組的順序並不重要。Maven將在拓撲上對模組進行排序,這樣依賴項總是在依賴模組之前構建。

  繼承和聚合建立了一個良好的動態,通過一個單一的高階POM來控制構建。你經常會看到既有繼承又有聚合的專案。例如,整個maven核心都是通過一個基本的POM org.apache.maven:maven

來執行的。因此構建maven專案可以由單個命令執行:mvn compile。然而,儘管就整個POM專案而言,一個聚合專案和一個繼承專案是不一樣的,不應該被混淆。一個POM專案可能來自於繼承但不是必須的——它還可能是其它任何型別的聚合模組。相反,一個POM專案可能只涉及到聚合而不涉及到繼承。

  下面我們舉例來說明,之前的文章中,我們已經成功的建立了兩個Maven專案,一個是my-app,另一個是maven-parent,這兩個專案都是採用的繼承的模式,現在我們可以用聚合的方式將其組合成一體,比如說將maven-parent聚合到my-app中,具體的做法是修改my-app中的父類pom.xml即可。

  my-app中的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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>myapp1</module>
    <module>myapp2</module>
    <module>myapp3</module>
    <module>myapp4</module>
    <module>myapp5</module>
    <module>myapp6</module>
    <module>my-app-site</module>
    <module>my-webapp</module>
    <module>maven-parent</module>
  </modules>
  <name>my-app</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

  通過這樣的變化,它們就成功的聚合到了一起,通過在my-app中的pom.xml執行相應的構建,其所聚合的專案maven-parent也會被一起構建。

  詳細的程式碼可以參考下面的連結:

2、繼承

  在之前的文章中,我就已經多少談到了Maven的繼承,在這裡我重點談一下Maven的繼承原則,在Maven中一共有兩大繼承原則。

其一是:短路優先原則

  我們假設有專案D,專案E,專案F三個專案,在專案D,和專案E中都存在一個類Say,它們的原始碼如下:

  專案D中的類Say:

package com.lyc;

public class Say {

    public String say(){
        return "D";
    }
}

  專案E中的類Say:

package com.lyc;

public class Say {

    public String say(){
        return "E";
    }
}

  在專案E中存在測試類SayTest,在專案F中也存在測試類SayTest,它們的原始碼都相同,都如下:

  專案E、F中的類SayTest

package com.lyc;

import org.junit.Test;

public class SayTest {

    @Test
    public void test(){
        Say say = new Say();
        System.out.println(say.say());
    }

}

  由於我們知道,Maven允許繼承,在這種情況下,F依賴了E,E又依賴了D,這樣在執行F中的SayTest類時,我們根據最短路徑原則不難知道,在F中執行的是輸出專案E中的Say類,此時我們輸出為E。

  當我們在執行專案E中的SayTest類時,其輸出的也是E,這也同樣不違反該定律,因為畢竟呼叫自身的Say,類要比呼叫依賴的Say類依賴路徑更短。

  詳細的原始碼如下:

其二是:誰先宣告,先解析誰

  這個比較好理解,就是我們假設現在有三個專案,分別為專案H、專案I、專案J三個專案,現在在專案H,和專案I中都存在類Say,然後在專案J中存在測試類SayTest,下面是專案J中的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">
    <parent>
        <artifactId>maven-parent3</artifactId>
        <groupId>com.lyc</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>J</artifactId>
    <packaging>jar</packaging>

    <name>J</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.lyc</groupId>
            <artifactId>H</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.lyc</groupId>
            <artifactId>I</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

  在專案J中執行測試類SayTest,根據誰先宣告,先解析誰的原理,由於專案H在專案J中優先宣告,因而在專案J中呼叫SayTest時輸出的內容為“H”。

  專案的詳細原始碼如下: