原文:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
当我们在使用Maven做一些工作,如打包,编译,运行测试等等任务时,我们已经使用到了Maven中的几个重要概念:
lifecycle, phase and goal。
例如,如果我们使用ant打包,我们需要清晰的在脚本中告诉ant:
源代码在哪,打包的目标文件类型如jar,目标文件夹在哪。首先要编译,然后运行测试,最后打包。
而Maven为了在最大程度上简化我们的工作,因而定义了lifecycle, phase and goal。我们仅仅需要简单的运行:
mvn package(package是一个phase), 包就自动打好了。
而实际上,mvn package这个命令会运行以下6个步骤(左边这列是步骤名,同时也是phase的名字,右边是对应的goal):
process-resources | resources:resources |
compile | compiler:compile |
process-test-resources | resources:testResources |
test-compile | compiler:testCompile |
test | surefire:test |
package | jar:jar |
因此使用Maven打包时,用到的信息和步骤一点都不比用ant少,只不过使用到的信息,定义在了POM文件中(本文并不涉及);而步骤定义在了lifecycle, phase and goal中。
也就是说,Maven定义了一系列的best practice。
在这里,对与打包这个任务,我们仅需要使用Maven中已经定义好的这些best practice,就能简单的完成日常工作了。
下面我们首先介绍这些best practice,也就是定义好的lifecycle, phase, goal。
之后介绍如果我们不想使用best practice,比如,我们想在打包时,在上面的test-complie(这个步骤仅编译测试代码,但不会运行测试用例)之后,运行测试。同时,还希望能使用一个第三方工具检查测试用例的代码覆盖率,并形成一个报表。也就是说,我们希望在打包结束时,同时得到一个测试代码覆盖率的报告,应该怎么做。
现在开始~
有三种内置的build lifecycle:The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while thesite lifecycle handles the creation of your project's site documentation.
For example, the default lifecycle has the following build phases (这里并不包含所有的phase,只是举例):
1,validate - validate the project is correct and all necessary information is available
2,compile - compile the source code of the project
3,test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
4,package - take the compiled code and package it in its distributable format, such as a JAR.
5,integration-test - process and deploy the package if necessary into an environment where integration tests can be run
6,verify - run any checks to verify the package is valid and meets quality criteria
7,install - install the package into the local repository, for use as a dependency in other projects locally
8,deploy - done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
执行一个phase将会执行这个lifecycle前面的所有phase。
下面这个例子执行了clean lifecycle和default lifecycle到install为止的所有phase。
mvn clean install
However, even though a build phase is responsible for a specific step in the build lifecycle, the manner in which it carries out those responsibilities may vary.
And this is done by declaring the goals bound to those build phases.
A goal represents a specific task (finer than a build phase) which contributes to the building and managing of a project.
也就是说,执行phase实际执行的是goal。如果一个phase没有绑定goal,那这个phase就不会被执行。
一些phase默认已经绑定了一些goal。对于default lifecycle来说, 这些被绑定的goal并不完全相同,而是和packaging value相关。所谓的packaging value就是
<packaging>jar</packaging>//这个很好理解,对于不同的包类型,打包的过程不尽相同,因此需要执行的goal也不同。
一个goal是独立的,它可以被绑定到多个phase中去,也可以一个phase都没有。如果一个goal没有被绑定到任何一个lifecycle,它仍然可以直接被调用,而不是被lifecycle调用。
因此可以这样理解phase与goal的关系:
phase其实就是goal的容器。实际被执行的都是goal。phase被执行时,实际执行的都是被绑定到该phase的goal。
goal与goal之间是独立的。因此单独执行一个goal不会导致其他goal被执行。
下面的例子
mvn clean dependency:copy-dependencies package
clean是phase。
dependency:copy-dependencies是plugin-in dependency 的goal copy-dependencies。
package也是一个phase。
maven会顺序执行这3个对象中包含的所有goal。
Plugin
另外一种将goal绑定到phase的方法就是在project中使用plugin。即在POM中配置。
Plugins are artifacts that provide goals to Maven. Furthermore, a plugin may have one or more goals wherein each goal represents a capability of that plugin.
这里我们先思考一个问题,goal的本质是什么?
例如我们上面提到的需要,希望在打包时得到一个测试代码覆盖率的报告。
实现的方法就是:
1,将计算代码覆盖率的工具,例如cobertura,安装到Maven的repository中。此时cobertura就是一个plugin。
最简单的方法就是将cobertura加到项目的dependency中就行了。Maven会自动去网上的公共repository中下载项目依赖的的dependency到本地的repository中。
2,修改POM文件(可参考下面的pom的例子),将这个plugin,连同要执行的goal,加到package这个phase中去。
由于现在Maven已经非常流行,所以这些工具的官网上都会提供在Maven中使用该工具时,应使用什么命令。
参考cobertura网站,我们可以知道对于这个工具,对应的命令是:
mvn cobertura:cobertura (即phase和goal的名字都是cobertura)
3,此时再运行mvn package,就会运行cobertura这个plugin的goal,也就是cobertura。
之后我们就会在默认的位置找到生成的报表。
因此,goal其实是由存在于Maven的repository中的plugin提供的一个个小的功能程序。
它是Maven的lifecycle以及phase的基本组成元素。同时,我们也可以通过将各种各样的goal加入到Maven的phase中,从而根据自己的实际需求,灵活实现各种定制功能。
下面是一个更general的例子,该POM中展示了,如何将display-maven-plugin中的goal time绑定到process-test-resources这个phase中。
<plugin>
<groupId>com.mycompany.example</groupId>
<artifactId>display-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>time</goal>
</goals>
</execution>
</executions>
</plugin>
...
通过前面的例子我们明白,完全可以自行开发一个java程序,作为goal绑定到phase中后执行。
但Maven对嵌入到它之中的plugin有一些标准,在开发程序时需要遵循。
下面链接中列出了主要的Maven plugin。
http://maven.apache.org/plugins/index.html
同时关于plugin还可以参考下面链接中的plugin文档,得到更详细的解释。
http://maven.apache.org/guides/index.html