Maven 用了一段时间。每当遇到问题去查阅资料时,总能在各种特性和插件中找到满意的,甚至是超出预期的答案(这种感觉在用 Sonar 时也有),Maven 的强大可见一斑。
初学 Maven 时,即遇到“生命周期 (Lifecycle)”这个词,但之前原来一直有些误解,直到最近才完全弄懂相关的含义,这里说一说。目前 Maven 的最新版本为 3.0.4,本文相关内容都基于该版本。
Lifecycle
Lifecycle 定义了构建项目的流程。这里的“定义”其实是预定义(不知是否能自定义?),Maven 预定义了三种 lifecycle:
- clean
- default
- site
顾名思义,clean 用于清理项目,default 则是构建项目的标准流程(编译、打包、部署等),site 能生成项目的文档。每个 lifecycle 包含了一个 phase 列表,例如 clean 包含了 pre-clean、clean、post-clean 三个 phase,而 default 则包含了 compile、package、deploy 等二十三个 phase。
Phase
Phase 的定义是比较容易让人误解的,特别是如果你之前用过 Ant。Phase 乍看上去很像 Ant 的 target,但二者其实有一个关键的不同点:
- Ant 的 target 本身已经包含了任务信息,一个 target 执行什么任务是固定的
- Maven 的 phase 本身不包含任何任务信息,而是通过绑定 goal 来执行任务
用编程来打比方,target 就像一个普通的实现方法,而 phase 则是一个接口定义。例如,Maven 希望 compile 这个 phase 就做编译项目的任务,并且也给出了一个默认实现,但我们可以有自己的实现,在运行 compile 时想干嘛干嘛。
Goal
那如何控制 phase 的实现呢?就是通过绑定 goal 来控制的。Goal 是由插件定义的,一个插件可以定义多个 goal,例如 compiler 插件定义了 compile、testCompile 和 help 三个 goal。一个 goal 定义了一个操作,例如编译代码、复制资源文件、打包项目等。在配置插件时,可以将一个 goal 绑定到一个或多个 phase,这样在运行这个 phase 时就会运行绑定的 goal 了。
Maven 默认会有一些 phase - goal 绑定,这个默认值根据项目的打包方式 (POM 中的 <packaging>) 不同而有所不同,例如打包方式为 war 的项目,默认有以下 phase - goal 绑定:
- process-resources resources:resources
- compile compiler:compile
- process-test-resources resources:testResources
- test-compile compiler:testCompile
- test surefire:test
- package war:war
- install install:install
- deploy deploy:deploy
最后,举个例子总结。当我们运行 mvn package 命令构建项目时,Maven 的处理步骤如下:
- 由 package 这个 phase 确定当前的生命周期为 default
- 从 default 生命周期的第一个 phase 开始,按顺序运行至 package 这个 phase
- 运行某个特定 phase 时,如果有绑定 goal,则运行这些 goal。如果没有绑定 goal,则跳过当前 phase
更详细的信息,可参考 Lifecycle