乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 介绍与核心概念

    • Maven是什么
    • 约定优于配置
  • 第2章 安装与配置

    • 安装与验证
    • settings.xml
    • 本地仓库与镜像
  • 第3章 POM与项目坐标

    • POM
    • GAV坐标
    • packaging
  • 第4章 标准目录布局

    • 标准目录布局
  • 第5章 依赖机制

    • dependencies
    • scope
    • 依赖传递
    • 依赖冲突与调解
    • exclusions
    • optional
    • dependencyManagement
  • 第6章 仓库

    • 仓库体系
    • 本地仓库
    • 远程仓库与镜像
    • 私服
  • 第7章 构建生命周期

    • 生命周期概述
    • clean 生命周期
    • default 生命周期
    • site 生命周期
    • 生命周期与插件绑定
  • 第8章 插件

    • 插件概述
    • maven-compiler-plugin
    • maven-surefire-plugin
    • maven-war-plugin
  • 第9章 继承与聚合

    • parent继承
    • 聚合
    • BOM
    • properties
  • 第10章 属性与资源过滤

    • 资源过滤
    • Profile
  • 第11章 常用命令

    • mvn compile
    • mvn test
    • mvn package
    • mvn clean
    • mvn install
    • mvn dependency:tree
  • 第12章 常见问题与最佳实践

    • 依赖冲突排查
    • 最佳实践

生命周期概述

本章是"构建生命周期"主题的起点。理解生命周期的概念、三套生命周期的分工,以及阶段(Phase)与插件目标(Goal)的关系,是后续学习 clean、default、site 各阶段细节,以及理解插件绑定机制的前提。


核心机制

Maven 基于构建生命周期的概念。这意味着构建和分发特定构件的过程被明确定义。强调:

对构建项目的人来说,只需学习一小套命令,就能构建任何 Maven 项目,而 POM 会确保他们获得期望的结果。这是 Maven"约定优于配置"在构建流程上的直接体现——你不需要告诉 Maven"先编译再测试再打包",你只需要说 mvn package,Maven 自己知道该做什么。

生命周期的概念

Maven 的生命周期是一组预定义的、有序的构建阶段(Phase)集合。每个阶段代表构建过程中的一个步骤,如编译、测试、打包。生命周期的核心设计原则是:

  1. 顺序性:阶段按固定顺序执行,不能跳过中间阶段
  2. 累积性:执行某个阶段时,该阶段之前的所有阶段都会自动执行
  3. 插件驱动:每个阶段本身不做事,而是绑定一个或多个插件目标(Goal)来执行具体任务

三套生命周期

Maven 有三套相互独立的生命周期,它们之间没有依赖关系,可以单独调用:

生命周期用途典型命令
clean清理构建产物mvn clean
default编译、测试、打包、部署mvn compile、mvn test、mvn package、mvn install、mvn deploy
site生成项目文档站点mvn site

关键特性:三套生命周期是独立的。执行 mvn clean 不会触发 default 生命周期的任何阶段;执行 mvn package 也不会自动清理 target/ 目录。这就是为什么常见的组合命令是 mvn clean package——显式调用两个生命周期。

阶段(Phase)的概念

阶段是生命周期中的单个步骤。每个生命周期由多个阶段按顺序组成。以 default 生命周期为例,核心阶段包括:

validate → compile → test → package → verify → install → deploy

阶段的累积性是 Maven 最重要的行为特征之一。当你执行:

mvn package

Maven 实际上会依次执行:

validate → compile → test → package

package 之前的所有阶段都会自动运行,你不需要逐个敲命令。

生活类比:汽车生产线

想象 Maven 是一套汽车组装流水线:

  • 生命周期 = 整条流水线:有的流水线负责"组装新车"(default),有的负责"拆解旧车"(clean),有的负责"拍摄宣传册"(site)
  • 阶段 = 流水线上的工位:组装流水线上有"焊接车架"(compile)、"安装发动机"(test)、"喷漆质检"(package)等工位
  • 插件目标 = 工位上的机器人:每个工位本身只是一块空地,真正干活的是机器人(插件)。"焊接车架"工位上可能有一台焊接机器人(maven-compiler-plugin)
  • 累积性 = 流水线不可跳跃:你不能直接把车开到"喷漆质检"工位,它必须先经过前面的所有工位。当你说"我要一辆成品车"(mvn package),流水线自动从第一个工位开始,一路送到最后一个工位

这个类比的关键在于:生命周期是"流程框架",阶段是"流程节点",插件是"执行实体"。三者分离的设计,让 Maven 既能保证构建顺序的一致性,又能通过替换插件实现灵活的构建逻辑。


图示

上图展示了三套生命周期的并列关系。它们彼此独立,没有箭头相连。你可以单独调用 mvn clean,也可以单独调用 mvn package,也可以组合调用 mvn clean deploy。

上图展示了生命周期 → 阶段 → 插件目标的三层层次结构:

  • 生命周期是最高层抽象,定义"要做什么类型的事"
  • 阶段是中间层,定义"按什么顺序做"
  • 插件目标是最底层,定义"具体怎么做"

一个阶段可以绑定多个插件目标(如 package 阶段可能同时绑定 maven-jar-plugin:jar 和 maven-source-plugin:jar-no-fork),但一个插件目标通常只绑定到一个阶段。


完整示例

场景

飞翔科技的 employee-system 项目刚完成一次功能迭代。CTO 大翔要求架构师白歌向团队演示 Maven 生命周期的基本用法,确保后端小崔、前端黄俪、运维李眉都能理解"一条命令背后发生了什么"。

操作前:对生命周期一无所知

小崔之前用 IDE 的"Build"按钮,只知道"点一下就能跑",但不清楚 Maven 在背后执行了哪些步骤。黄俪作为前端,偶尔需要启动后端服务联调,对 Maven 命令更是一头雾水。

操作步骤

白歌在项目根目录下依次执行以下命令,并解释每个命令触发的生命周期:

步骤 1:清理构建产物

mvn clean

输出:

[INFO] --- maven-clean-plugin:3.2.0:clean (default-clean) @ employee-system ---
[INFO] Deleting /home/baige/employee-system/target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

说明:触发了 clean 生命周期的 pre-clean → clean → post-clean 阶段。实际执行的是 maven-clean-plugin:clean 目标,删除了 target/ 目录。

步骤 2:编译主代码

mvn compile

输出:

[INFO] --- maven-resources-plugin:3.3.0:resources (default-resources) @ employee-system ---
[INFO] Copying 2 resources
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ employee-system ---
[INFO] Compiling 15 source files to /home/baige/employee-system/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

说明:触发了 default 生命周期的 validate → compile 阶段。validate 阶段验证项目结构和 POM 合法性;compile 阶段调用 maven-compiler-plugin 将 src/main/java 编译到 target/classes。

步骤 3:运行测试并打包

mvn package

输出(节选):

[INFO] --- maven-resources-plugin:3.3.0:resources (default-resources) @ employee-system ---
[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ employee-system ---
[INFO] --- maven-resources-plugin:3.3.0:testResources (default-testResources) @ employee-system ---
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ employee-system ---
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ employee-system ---
[INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
[INFO] --- maven-jar-plugin:3.3.0:jar (default-jar) @ employee-system ---
[INFO] Building jar: /home/baige/employee-system/target/employee-system-1.0.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

说明:触发了 default 生命周期的 validate → compile → test → package 阶段。由于阶段的累积性,package 会自动先执行前面的所有阶段。最终生成 target/employee-system-1.0.0.jar。

操作结果

变化分析:

  • 小崔理解了 mvn compile 和 mvn package 的区别:前者只编译主代码,后者还会运行测试、打包 JAR
  • 黄俪学会了在联调前执行 mvn clean package,确保拿到的是"从零开始、完整构建"的产物,而非被旧文件污染的半成品
  • 李眉明白了为什么 Jenkins 流水线里用 mvn clean deploy 而不是 mvn deploy——clean 和 default 是两个独立的生命周期,必须显式组合才能既清理又部署

易错点与常见问题

误区一:生命周期是"脚本"

错误认知:"Maven 生命周期跟 Shell 脚本一样,就是按顺序执行一堆命令。"

纠正:生命周期不是脚本,而是声明式的阶段框架。脚本里写死了"先执行 A 命令,再执行 B 命令";而 Maven 生命周期只声明了"阶段顺序",每个阶段具体做什么由绑定的插件决定。你可以在不改变生命周期的情况下,替换 compile 阶段绑定的编译器插件(如从 maven-compiler-plugin 换成 maven-scala-plugin),生命周期本身不变。这种"框架与实现分离"的设计,是 Maven 与 Ant 的本质区别。

误区二:三套生命周期是串行执行的

错误认知:"执行 mvn clean package 时,Maven 先完整执行 clean 生命周期,再完整执行 default 生命周期,所以 clean 总是在 package 之前。"

纠正:mvn clean package 中两个生命周期的执行顺序确实是 clean 先、default 后,但这不是因为生命周期之间有依赖关系,而是因为命令行中 clean 写在 package 前面。Maven 按命令行顺序调度生命周期。如果你写 mvn package clean,Maven 会先执行 default 到 package,再执行 clean——虽然这通常不是你想要的结果。三套生命周期在设计上完全独立,它们的执行顺序由命令行参数决定,而非内置依赖。

误区三:执行 mvn test 只会运行测试

错误认知:"我只想看测试跑不跑得过,所以 mvn test 应该只执行测试,不会编译。"

纠正:由于阶段的累积性,mvn test 会自动先执行 validate 和 compile。如果 src/main/java 里的代码有编译错误,mvn test 会在编译阶段就失败,根本不会进入测试阶段。如果你只想运行测试而不重新编译,需要使用插件的直接调用方式:mvn surefire:test(跳过生命周期,直接调用插件目标)。


小结

Maven 的生命周期是构建流程的"骨架",由三套相互独立的生命周期(clean、default、site)组成。每套生命周期包含多个有序的阶段,执行某个阶段时会自动累积执行其前面的所有阶段。阶段本身不执行具体任务,而是绑定插件目标来完成实际工作。理解"生命周期 → 阶段 → 插件目标"的三层结构,是掌握 Maven 构建原理的核心。

本章与全局的关系:本章描绘了生命周期的"全景地图"。接下来四章将分别深入 clean、default、site 三套生命周期的阶段细节,以及生命周期与插件的绑定机制,让你从"知道有生命周期"进化为"能精确控制每个构建步骤"。

下一页
clean 生命周期