2.1 一次完整构建的旅程:三套生命周期


文档摘要

2.1 一次完整构建的旅程:三套生命周期 本节摘要:Maven 的构建过程由 clean、default、site 三套生命周期组织,default 是主战场,从 validate 到 deploy 共二十余个阶段。执行任一阶段会连带执行其全部前置阶段,而阶段本身是空壳,实际工作由绑定的插件完成。本节逐阶段走完一次完整构建,建立构建日志的全景解读能力。 一、从一条奇怪的报错说起 先看一个真实对话。新人问:"我只执行了 mvn test,为什么它把代码也编译了?测试不是只跑测试吗?" 这个疑问背后就是生命周期的核心语义:阶段不是孤立动作,而是一条传送带上的工位。你指定了终点站 test,机器就从 validate 一路站站开过来——compile 自然被路过并执行。

2.1 一次完整构建的旅程:三套生命周期

本节摘要:Maven 的构建过程由 clean、default、site 三套生命周期组织,default 是主战场,从 validate 到 deploy 共二十余个阶段。执行任一阶段会连带执行其全部前置阶段,而阶段本身是空壳,实际工作由绑定的插件完成。本节逐阶段走完一次完整构建,建立构建日志的全景解读能力。

一、从一条奇怪的报错说起

先看一个真实对话。新人问:"我只执行了 mvn test,为什么它把代码也编译了?测试不是只跑测试吗?" 这个疑问背后就是生命周期的核心语义:阶段不是孤立动作,而是一条传送带上的工位。你指定了终点站 test,机器就从 validate 一路站站开过来——compile 自然被路过并执行。

这种设计的价值在于确定性:任何人以任何方式触发 test 阶段,前置条件永远满足,不存在"忘了编译就跑测试"的状态。代价是你必须记住这条隐含的顺序链,否则会出现"我只是想重新打包,为什么测试又全跑了一遍"的困惑——答案在第 1.3 节的 -DskipTests 参数里。

二、三套生命周期全景

Maven 内置三套生命周期,各自独立、互不自动串联。

图:三套生命周期的阶段地图

图:三套生命周期的阶段地图

default 生命周期的完整阶段列表比图上更细(generate-resources、process-resources、generate-test-sources、process-test-sources、process-classes 等),日常高频的是图中九个。有两个阶段容易被忽视但战术价值很高:verify 挂载集成测试与质量检查(第 5 章的 SonarQube 常绑这里),process-resources 是资源过滤的执行点(2.3 节的主角)。

三、跟着日志走一遍完整旅程

对 risk-engine 执行 mvn clean install,把输出按生命周期分段标注:

[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ risk-engine --- [INFO] Deleting 目录 target // ↑ clean 生命周期的 clean 阶段:删除构建输出目录 [INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ risk-engine --- [INFO] Copying 3 resources // ↑ process-resources 阶段:拷贝并过滤主资源 [INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ risk-engine --- [INFO] Compiling 42 source files with javac // ↑ compile 阶段:编译主源码到 target/classes [INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ risk-engine --- [INFO] Tests run: 87, Failures: 0, Errors: 0 // ↑ test 阶段:执行单元测试 [INFO] --- maven-jar-plugin:3.2.2:jar (default-jar) @ risk-engine --- [INFO] Building jar: target/risk-engine-1.0.0.jar // ↑ package 阶段:打成 jar [INFO] --- maven-install-plugin:2.5.2:install (default-install) @ risk-engine --- [INFO] Installing jar 到本地仓库路径 // ↑ install 阶段:把成品放进本地仓库 [INFO] BUILD SUCCESS (总耗时: 12.3 s)

日志里的格式值得记住:插件:版本:goal (绑定的执行id) @ 模块。以后看到任何一行,都能立刻拆出"谁(插件)、干什么(goal)、在哪个模块"。这也解释了为什么 Maven 号称生命周期却从不自己干活——阶段只是时间表,执行者全是插件,这是下一节的主题。

补一段每个值班工程师迟早要答的题:两条生命周期的默认绑定都发生在哪些阶段。以 jar 打包为例,default 生命周期里真正有插件值守的阶段不多——资源处理两站、编译两站、surefire 的 test、jar 插件的 package、install 与 deploy 各一站,其余阶段(validate、verify 等多数)默认是空的,静默通过。这解释了一个高频疑惑:为什么 mvn verify 好像"什么都没多做"就过了?因为 verify 阶段默认没有绑定任务,它的价值在于给你一个挂载点——集成测试框架与质量检查插件(第 5 章的 SonarQube)都绑这里。空阶段不是设计缺陷,是预留的接口。

阶段 jar 项目的默认值守 说明
process-resources resources 插件 拷贝并过滤主资源 2.3 节主战场
compile compiler 插件 主源码编译
process-test-resources resources 插件 测试资源处理
test-compile compiler 插件 测试源码编译
test surefire 插件 单元测试执行
package jar 插件 打成 jar
verify 默认空 集成测试与质量检查的挂载点
install install 插件 装入本地仓库
deploy deploy 插件 上传远程仓库

顺带回答本节开头的新人问题反过来的一面:既然执行 test 必然先 compile,那"只编译不测试"怎么写?mvn compilemvn test-compile(编译测试代码但不执行)。两类需求,生命周期都给了对应的站点。

本节要点回顾

  • 三套生命周期独立:clean、default、site;mvn clean package 是手动串联两套,不是一套内的顺序;
  • 执行即前置:指定某阶段会连带执行全部前置阶段,确定性由此而来;
  • 高频九阶段:validate、compile、test、package、verify、install、deploy 加上资源处理两个阶段,覆盖日常九成场景;
  • 日志格式可拆解插件:版本:goal (执行id) @ 模块,每一行都能定位到生命周期位置;
  • 阶段是空壳插件是工人:没有绑定插件的阶段静默跳过,自定义行为全靠绑定(下一节展开)。

生命周期的时间表已经摊开,但真正在工位上拧螺丝的插件军团还没露面。下一节讲它们的编制:默认绑定怎么来、goal 怎么直接调用、以及如何往军团里塞一个你自己写的新兵。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U