bigywater.tech
Java · 430

Maven 生命周期:阶段与插件目标如何组合

Maven 的生命周期由阶段构成,而阶段本身不做事,插件目标绑定到阶段上才执行。这篇用一个真实的 jar 项目验证:每个阶段累加执行哪些目标、绑定顺序、直接调用目标的后果、两个跳过测试的开关以及失败时的行为。

30 个
Maven 3.10.0 错误信息列出的合法阶段(clean 3 + default 23 + site 4)
2 / 5 / 6 / 7
jar 打包下 mvn compile / test / package / install 执行的目标数(validate 为 0、verify 仍是 6)
0 个 .class
没有先编译就执行 mvn jar:jar 得到的 jar 里的类文件数(rc 仍是 0,只有一条警告)

阶段累加执行的目标

实测 · 本机执行输出
  mvn no-such-phase 的错误信息列出的合法阶段:30 个:pre-clean,clean,post-clean,validate,initialize,generate-sources,process-sources,generate-resources,process-resources,compile,process-classes,generate-test-sources,process-test-sources,generate-test-resources,process-test-resources,test-compile,process-test-classes,test,prepare-package,package,pre-integration-test,integration-test,post-integration-test,verify,install,deploy,pre-site,site,post-site,site-deploy
  mvn validate:rc=0,执行 0 个目标:(无)
  mvn compile:rc=0,执行 2 个目标:resources:resources → compiler:compile
  mvn test:rc=0,执行 5 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test
  mvn package:rc=0,执行 6 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test → jar:jar
  mvn verify:rc=0,执行 6 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test → jar:jar
  mvn install:rc=0,执行 7 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test → jar:jar → install:install

同一阶段内的执行顺序

实测 · 本机执行输出
  mvn compile:执行 5 个目标(含 id):resources:copy-resources[early] → resources:resources[default-resources] → resources:copy-resources[zz-first] → resources:copy-resources[aa-second] → compiler:compile[default-compile]
  target 下生成的目录:classes,extra0,extra1,extra2,generated-sources,maven-status

直接调用插件目标

实测 · 本机执行输出
  全新项目 mvn compiler:compile:rc=0,执行 1 个目标:compiler:compile;target/classes 内容:App.class;src/main/resources 的 a.txt 被复制了吗:False
  全新项目 mvn jar:jar(没有先编译):rc=0,执行 1 个目标:jar:jar;jar 里的条目数 7,其中 .class 0 个;警告:JAR will be empty - no content was marked for inclusion!
  先 mvn compile 再 mvn jar:jar:jar 条目数 9,其中 .class 1 个,a.txt 1 个
  mvn compile surefire:test(阶段与目标混用):执行 3 个目标:resources:resources → compiler:compile → surefire:test

跳过测试的两个开关

实测 · 本机执行输出
  第一次 mvn package:6 个目标,日志 "Compiling" 行:Compiling 1 source file with javac [debug release 17]; Compiling 1 source file with javac [debug release 17]
  第二次 mvn package(没有改动):6 个目标,日志:Nothing to compile - all classes are up to date.; Nothing to compile - all classes are up to date.; Tests run: 1, Failures: 0, Errors: 0, Skipped: 0;"Building jar" 日志行数:第一次 1,第二次 0(jar 没有改动时 jar 目标不再重新打包,也不打日志)
  mvn package -DskipTests:6 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test → jar:jar
      日志:Compiling 1 source file with javac [debug release 17] to target/classes; Compiling 1 source file with javac [debug release 17] to target/test-classes; Tests are skipped.
  mvn package -Dmaven.test.skip=true:6 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test → jar:jar
      日志:Not compiling test sources; Tests are skipped.
      target 下是否有 test-classes:False

失败时的后续阶段

实测 · 本机执行输出
  测试失败时 mvn package:rc=1,执行 5 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test;生成 jar:False;结果:[ERROR] BUILD FAILURE
  加 -Dmaven.test.failure.ignore=true:rc=0,执行 6 个目标:resources:resources → compiler:compile → resources:testResources → compiler:testCompile → surefire:test → jar:jar;生成 jar:True;Tests run: 1, Failures: 1, Errors: 0, Skipped: 0

分步演示

Maven 生命周期
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。Maven 3.10.0(Homebrew),JDK 21.0.12,compiler 3.16.0 / resources 3.5.0 / surefire 3.6.0 / jar 3.5.1 / install 由 Maven 默认版本决定;离线 -o 运行,目标列表来自日志里的 --- 插件:版本:目标 (id) @ 项目 --- 行;JUnit Jupiter 5.10.2;install 目标写入 ~/.m2 后已删除
    • 没有验证:多模块 reactor 的阶段执行顺序、并行构建 -T、profile 与继承带来的绑定变化、自定义生命周期扩展(.mvn/extensions.xml)、war / pom / maven-plugin 等其它打包类型的默认绑定、Maven 4 的变化、站点生命周期与 deploy 阶段
    京ICP备2026067502号-1京公网安备11010502063487号