maven內部執行原理解析(二)
在第一篇裡主要介紹了maven的幾個核心概念,這一篇裡我們就以一個簡單的例子來分析整個maven執行的過程。構建所使用的專案結構如下:
專案結構主要是一個echo專案,其包含了兩個module,分別是api和biz。echo專案的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>org.maven</groupId>
<artifactId>echo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>api</module>
<module >biz</module>
</modules>
</project>
這裡有個比較費解的地方就是<packaging>pom</packaging>。若<packaging>元素的內容是jar,那麼我們很好理解,也就是說這個專案最終會被打包成一個jar包。那<packaging>元素為pom又是什麼意思呢?從字面上的意思來看,這個專案將打包成一個pom。我們不妨去maven倉庫裡去瞧瞧(前提是已經在專案下運行了mvn install命令)。我們發現在<maven倉庫路徑>/org/maven/echo/1.0.0目錄下有一個echo-1.0.0.pom檔案,細心的讀者可能已經發現這個檔案其實和echo專案中的pom.xml是同一個檔案。這樣做的目的是什麼呢?還記得
管理子專案
例如這裡的api和biz就是echo專案的兩個module。若沒有echo這個父專案,我們需要到api和biz兩個專案下分別執行mvn install命令才能完成整個構建過程,而有了echo這個父專案之後,我們只需在echo專案中執行mvn install即可,maven會解析pom.xml,發現該專案有api和biz兩個module,它會分別到這兩個專案下去執行mvn install命令。當module數量比較多的時候,能大大提高構建的效率。管理繼承屬性
比如api和biz都需要某個依賴,那麼在echo專案的pom.xml中宣告即可,因為根據PO物件的繼承關係,api和biz專案會繼承echo專案的依賴,這樣就可以減少一些重複的輸入。
effective pom包含了當前專案的PO物件,直到Super POM對應的PO物件中的資訊。要看一個專案的effective pom,只需在專案中執行
mvn help:effective-pom
命令即可檢視。這裡順帶說一句,有的同學可能不理解上面這個命令是什麼意思。maven命令的語法為
mvn [options] [goal(s)] [phase(s)]
這裡出現了第一篇中講述的兩個概念:goal和phase。maven允許你執行一個或者多個goals/phases。很明顯這面的命令help:effective-pom並不是一個phase(maven構建過程中的phase請參考上一篇文章),那麼也就是說它是一個goal。對這個goal只不過是採用了縮寫的形式,其全稱是這樣的:
org.apache.maven.plugins:maven-help-plugin:2.2:effective-pom
以分號為分隔符,包含了groupId,artifactId,version,goal四部分。若groupId為org.apache.maven.plugins則可以使用上述的簡寫形式。也就是說
mvn help:effective-pom
mvn org.apache.maven.plugins:maven-help-plugin:2.2:effective-pom
是等價的,都是執行了maven-help-plugin這個plugin中的effective-pom這個goal。
好了,繼續回到effective pom。我們說過maven在真正構建的時候用的就是effective pom,那麼說明effective pom中包含了構建的所有資訊,我們以biz專案中的effective pom為例來看下effective pom長什麼樣子。在biz專案中執行mvn help:effective-pom命令,你會得到如下輸出:
<?xml version="1.0"?>
<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>org.maven</groupId>
<artifactId>echo</artifactId>
<version>1.0.0</version>
</parent>
<groupId>org.maven</groupId>
<artifactId>echo-biz</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.maven</groupId>
<artifactId>echo-api</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/src/main/java</sourceDirectory>
<scriptSourceDirectory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/src/test/java</testSourceDirectory>
<outputDirectory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/target/classes</outputDirectory>
<testOutputDirectory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/target/test-classes</testOutputDirectory>
<resources>
<resource>
<directory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/src/test/resources</directory>
</testResource>
</testResources>
<directory>/Users/allstarw/workspace/own-proj/misc/maven/echo/biz/target</directory>
<finalName>echo-biz-1.0.0</finalName>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>default-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-install</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-resources</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
<execution>
<id>default-testResources</id>
<phase>process-test-resources</phase>
<goals>
<goal>testResources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
篇幅有點長,省略了部分內容。對比biz專案的pom.xml,我們發現effective pom中增加了Super POM中繼承過來的一些配置,比如說<sourceDirectory>定義了biz專案的原始碼路徑,以及Lifecycle中各個phase繫結的goal:
[phase] [goal]
compile maven-compiler-plugin:2.3.2:compile
package maven-jar-plugin:2.3.2:jar
install maven-install-plugin:2.3.1:install
... ...
有了effective pom的概念之後,再來看maven構建的輸出日誌,是不是有點豁然開朗的感覺?
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] echo
[INFO] echo-api
[INFO] echo-biz
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building echo 1.0.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ echo ---
[INFO] Installing /Users/allstarw/workspace/own-proj/misc/maven/echo/pom.xml to /Users/allstarw/.m2/repository/org/maven/echo/1.0.0/echo-1.0.0.pom
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building echo-api 1.0.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ echo-api ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/allstarw/workspace/own-proj/misc/maven/echo/api/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ echo-api ---
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/allstarw/workspace/own-proj/misc/maven/echo/api/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ echo-api ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/allstarw/workspace/own-proj/misc/maven/echo/api/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ echo-api ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ echo-api ---
[INFO] No tests to run.
[INFO] Surefire report directory: /Users/allstarw/workspace/own-proj/misc/maven/echo/api/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ echo-api ---
[INFO] Building jar: /Users/allstarw/workspace/own-proj/misc/maven/echo/api/target/echo-api-1.0.0.jar
[INFO]
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ echo-api ---
[INFO] Installing /Users/allstarw/workspace/own-proj/misc/maven/echo/api/target/echo-api-1.0.0.jar to /Users/allstarw/.m2/repository/org/maven/echo-api/1.0.0/echo-api-1.0.0.jar
[INFO] Installing /Users/allstarw/workspace/own-proj/misc/maven/echo/api/pom.xml to /Users/allstarw/.m2/repository/org/maven/echo-api/1.0.0/echo-api-1.0.0.pom
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building echo-biz 1.0.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ echo-biz ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/allstarw/workspace/own-proj/misc/maven/echo/biz/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ echo-biz ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ echo-biz ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/allstarw/workspace/own-proj/misc/maven/echo/biz/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ echo-biz ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ echo-biz ---
[INFO] No tests to run.
[INFO] Surefire report directory: /Users/allstarw/workspace/own-proj/misc/maven/echo/biz/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ echo-biz ---
[INFO]
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ echo-biz ---
[INFO] Installing /Users/allstarw/workspace/own-proj/misc/maven/echo/biz/target/echo-biz-1.0.0.jar to /Users/allstarw/.m2/repository/org/maven/echo-biz/1.0.0/echo-biz-1.0.0.jar
[INFO] Installing /Users/allstarw/workspace/own-proj/misc/maven/echo/biz/pom.xml to /Users/allstarw/.m2/repository/org/maven/echo-biz/1.0.0/echo-biz-1.0.0.pom
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] echo .............................................. SUCCESS [0.461s]
[INFO] echo-api .......................................... SUCCESS [2.581s]
[INFO] echo-biz .......................................... SUCCESS [0.382s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.593s
[INFO] Finished at: Wed Jul 06 00:22:50 CST 2016
[INFO] Final Memory: 10M/156M
[INFO] ------------------------------------------------------------------------
日誌的輸出十分清楚,分別構建echo,api,biz這三個專案(因為biz專案依賴api專案,因此api專案需要首先構建)。對每個專案構建時,將lifecycle中的phase所對應的goal依次執行。現在你能夠看懂maven的輸出日誌了吧?還有疑問?請留言。