一、前言
Maven可以使用clean
、compile
、package
、install
等指令完成Java项目构建,一个典型的Maven指令为:mvn package
,该命令的控制台输出如下所示:
maven-resources-plugin:2.6:resources (default-resources)
maven-compiler-plugin:3.1:compile (default-compile)
maven-resources-plugin:2.6:testResources (default-testResources)
maven-compiler-plugin:3.1:testCompile (default-testCompile)
maven-surefire-plugin:2.12.4:test (default-test)
maven-jar-plugin:2.4:jar (default-jar)
在执行package
指令过程中,分别执行了resources
、compile
、testResources
、testCompile
、test
、jar
等操作。那么,这里的pacakge
指令,和其触发的resources
等操作,分别代表了什么,它们之间又有什么关系呢?
二、Maven生命周期阶段
Maven中有三个生命周期(Lifecycle):Clean
、Default
、Site
,一个生命周期中有多个阶段(Phases),生命周期与阶段的对应关系如下:
生命周期(Lifecycle) | 阶段(Phases) |
---|---|
Clean | clean |
Default | validate、initialize、process-sources、compile、process-test-resources、test-compile、test、package、integration-test、verify、install、deploy |
Site | site、site-deploy |
上表省略了部分阶段,有关阶段的更多内容详见Maven Lifecycle Reference。
mvn
命令可以触发一个生命周期阶段,如:mvn package
中的package
指令参数代表需要执行Default
生命周期中的package
阶段。同一生命周期中的每一个阶段都依赖于上一阶段,如:package
阶段依赖于test
阶段,即,执行package
阶段之前,肯定会先执行test
阶段,以此类推(执行顺序参见上表)。触发生命周期阶段时,其会寻找并执行绑定在该生命周期阶段下的所有执行目标,有关执行目标详见下节。
三、Maven插件中的执行目标
执行目标(Goals)是构建过程中的最小执行单位,它是由Maven插件提供的一个特定的任务。
(一)调用执行目标
执行目标可以直接调用,也可以通过生命周期阶段间接调用。
- 直接调用执行目标
maven通过mvn [plugin]:[goal]
的方式单独调用一个执行目标。如下所示:
mvn compiler:compile
该命令会调用compiler
插件下的compile
执行目标,这里的compiler
插件是maven-compiler-plugin
的缩写,官方插件maven-xxxxxx-plugin
都可以缩写成xxxxxx
。如果需要指定插件的版本,也可以使用mvn [groupId]:[artifactId]:[version]:[goal]
的形式,如下所示:
mvn org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile
- 触发生命周期阶段,间接调用绑定在其上的执行目标
maven通过mvn [phase]
的方式触发一个生命周期阶段,其会执行所有绑定在该生命周期阶段下的执行目标。如下所示:
mvn compile
该命令会触发compile
生命周期阶段,并执行绑定在该生命周期阶段上的所有执行目标。compile
生命周期阶段默认绑定了compiler:compile
执行目标,因此,在触发compile
生命周期阶段时,compiler:compile
执行目标也会跟着执行。
(二)生命周期阶段的默认执行目标
每个生命周期阶段都会有默认的执行目标,如下所示:
Phase | plugin:goal |
---|---|
clean | clean:clean |
process-resources | resources:resources |
compile | compiler:compile |
process-test-resources | resources:testResources |
test-compile | compiler:testCompile |
test | surefire:test |
package | ejb:ejb or ejb3:ejb3 or jar:jar or par:par or rar:rar or war:war |
install | install:install |
deploy | deploy:deploy |
阶段与执行目标的绑定关系详见Maven Built-in Lifecycle Bindings。
不管生命周期阶段有没有绑定其它执行目标,默认执行目标一般都会在触发对应生命周期阶段时自动执行。
(三)手动绑定执行目标的生命周期阶段
一个生命周期阶段除了默认的执行目标外,也可以绑定其它执行目标,一个简单示例如下(pom.xml
):
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
该配置将jacoco-maven-plugin
插件的report-aggregate
执行目标绑定到了verify
生命周期阶段上,后续执行mvn verify
后,report-aggregate
执行目标也会跟着执行。
当然,除了mvn verify
外,也可以单独调用mvn org.jacoco:jacoco-maven-plugin:0.7.9:report-aggregate
执行对应执行目标。
四、总结
综上,Maven通过生命周期阶段和插件中的执行目标共同完成整个构建流程,执行目标是构建过程中的最小执行单位,生命周期阶段是相关执行目标的集合。
以maven打包为例,在执行mvn package
时,其首先会触发Default
生命周期的package
阶段,依次执行Default
中的以下阶段:compile
-> test
-> package
(省略了部分阶段)。在执行这些阶段时,其会找到对应阶段绑定的所有执行目标(如:compile
阶段下的compiler:compile
执行目标、test
阶段下的surefire:test
执行目标、package
阶段下的jar:jar
执行目标、等等),并依次执行。
常用的mvn指令都是通过生命周期阶段来执行对应操作,格式为:mvn [phase]
,如:通过mvn clean
清除编译文件、通过mvn package
打包等等,它们的本质都是批量执行了一系列的maven插件执行目标。除此之外,也可以单独执行执行目标,格式为:mvn [plugin]:[goal]
,如:mvn compiler:compile
、mvn jar:jar
等等。
生命周期阶段会有默认执行目标,如有需要,也可以在pom.xml
中通过phase
手动指定对应执行目标的生命周期阶段。
参考文档