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是同一个文件。这样做的目的是什么呢?还记得第一篇中说过的PO对象吧,我们说过PO对象也是有继承关系的,比如说这里echo项目对应的PO对象就是api项目对应的PO对象的父对象(api项目是echo项目的一个module,在api项目的pom.xml中<parent>元素的内容所对应的就是echo项目),而echo项目PO对象的父对象又是哪个呢?答案是Super POM对应的PO对象。这就是maven中project inheritance的概念。当实际执行maven命令的时候,会根据project inheritance关系对项目的pom.xml进行转化,得到真正执行时所用到的pom.xml,即所谓的effective pom。而<packaging>pom</packaging>的作用就在这里。因此可以得到一个结论:所有<packaging>元素为pom的项目其实并不会输出一个可供外部使用,类似于jar包的东西。这类项目的作用有两个:

  • 管理子项目
    例如这里的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的输出日志了吧?还有疑问?请留言。

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

推荐阅读更多精彩内容

  • maven至今还是Java编程语言构建的事实标准,大部分项目还在使用maven来进行构建,因此了解maven内部运...
    zlwen阅读 18,982评论 18 88
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Maven简单介绍 Maven是一个项目管理工具。强大,但是很容易使用。 它包含了: 一个项目对象模型 (Proj...
    高公子Daniel阅读 4,149评论 4 60
  • 前言什么是 POMQuick Overview POM 常用元素 pom.xml 完整注释 参考 0 前言 什么是...
    seyvoue阅读 12,457评论 1 36
  • Maven编译代码的相关命令 第一、main目录下的主代码编写完毕后,使用Maven进行编译,在项目根目录下运行命...
    加油小杜阅读 1,112评论 0 2