clean 生命周期
本章承接"生命周期概述",聚焦 clean 生命周期。理解 pre-clean、clean、post-clean 三个阶段的分工,是掌握构建环境清理、避免旧产物干扰新构建的基础。
核心机制
clean 生命周期用于清理项目,包含三个阶段:pre-clean、clean、post-clean。说明:
最常用的阶段是 clean,它会删除 target 目录以及任何其他被配置为需要删除的目录或文件。需要特别注意的是,target 是默认被删除的目录,但你可以通过配置让 clean 阶段删除其他目录。
clean 生命周期的三个阶段
| 阶段 | 名称 | 作用 | 默认绑定的插件目标 |
|---|---|---|---|
pre-clean | 清理前阶段 | 执行一些需要在正式清理之前完成的准备工作 | 无默认绑定 |
clean | 清理阶段 | 删除构建输出目录(默认 target/) | maven-clean-plugin:clean |
post-clean | 清理后阶段 | 执行一些需要在清理之后完成的收尾工作 | 无默认绑定 |
mvn clean 的作用
当你执行 mvn clean 时,Maven 会依次执行 pre-clean → clean → post-clean。由于 pre-clean 和 post-clean 默认没有绑定任何插件目标,实际有可见效果的是 clean 阶段。
clean 阶段绑定的 maven-clean-plugin:clean 目标默认删除以下内容:
- 项目根目录下的
target/目录(包含编译后的.class文件、打包的 JAR/WAR、测试报告等) - 任何在
pom.xml中通过<filesets>额外配置的文件或目录
自定义清理范围
如果默认删除 target/ 不够,你可以在 pom.xml 中扩展 clean 插件的配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<filesets>
<fileset>
<directory>logs</directory>
<includes>
<include>*.log</include>
</includes>
</fileset>
<fileset>
<directory>temp</directory>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
上述配置会让 mvn clean 在删除 target/ 的同时,也删除 logs/ 目录下的所有 .log 文件和整个 temp/ 目录。
生活类比:餐厅打烊后的清台
想象一家餐厅(项目)每天营业结束后的清台流程:
- pre-clean = 清点贵重餐具:服务员先检查有没有客人落下的钱包、手机,确保不会误扔重要物品
- clean = 清理桌面和地面:把剩菜倒掉、擦桌子、扫地——这是清台的核心动作,对应删除
target/目录 - post-clean = 消毒和锁门:清理完成后,用消毒液擦拭,检查煤气阀门,最后锁门
这个类比的关键在于:clean 是核心动作,但 pre-clean 和 post-clean 提供了"钩子",让你可以在清理前后插入自定义逻辑。比如 pre-clean 阶段可以备份 target/ 里的测试报告,post-clean 阶段可以发送"构建环境已清理"的通知。
图示
上图展示了 clean 生命周期的阶段流程。clean 阶段是唯一的"有默认行为"的阶段,前后两个阶段是"空钩子",供开发者插入自定义逻辑。
完整示例
场景
飞翔科技的 employee-system 项目连续进行了多轮迭代,后端工程师小崔发现最近几次构建出现了诡异的行为:修改了代码但运行时还是旧逻辑、测试报告里混入了上次的失败记录。架构师白歌诊断后认为,是 target/ 目录里的旧产物没有被清理,建议小崔养成"每次正式构建前执行 mvn clean"的习惯,并向团队演示 clean 前后的目录变化。
操作前:target 目录被旧产物污染
小崔连续执行了多次构建命令,但没有清理过 target/。当前目录状态:
employee-system/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/feixiang/employee/
│ │ │ ├── EmployeeService.java # 最新代码
│ │ │ └── OldLogic.java # 已删除的源文件
│ │ └── resources/
│ └── test/
│ └── java/
└── target/
├── classes/
│ └── com/feixiang/employee/
│ ├── EmployeeService.class # 最新编译结果
│ └── OldLogic.class # ❌ 旧产物!源文件已删但 .class 还在
├── test-classes/
├── surefire-reports/ # 上次的测试报告
│ ├── com.feixiang.employee.EmployeeServiceTest.txt
│ └── com.feixiang.employee.OldTest.txt # ❌ 旧测试类已删但报告还在
└── employee-system-1.0.0.jar # 包含 OldLogic.class 的脏包
问题:
OldLogic.java已在上一轮重构中删除,但target/classes/OldLogic.class仍然存在mvn package打出的 JAR 包含了OldLogic.class,导致生产环境出现已废弃的逻辑- 旧测试报告
OldTest.txt干扰了测试结果的判断
操作步骤
步骤 1:执行 clean
小崔在项目根目录执行:
mvn clean
控制台输出:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< com.feixiang:employee-system >------------------
[INFO] Building employee-system 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.2.0:clean (default-clean) @ employee-system ---
[INFO] Deleting /home/xiaocui/employee-system/target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
步骤 2:验证清理结果
执行 ls target/(Windows 用 dir target):
ls target/
输出:
ls: cannot access 'target/': No such file or directory
target/ 目录已被完全删除。
步骤 3:重新完整构建
小崔执行组合命令:
mvn clean package
构建成功后,检查新的 target/ 目录:
target/
├── classes/
│ └── com/feixiang/employee/
│ └── EmployeeService.class # ✅ 只有当前存在的源文件对应的 .class
├── test-classes/
│ └── com/feixiang/employee/
│ └── EmployeeServiceTest.class
├── surefire-reports/
│ └── com.feixiang.employee.EmployeeServiceTest.txt # ✅ 只有当前测试的报告
└── employee-system-1.0.0.jar # ✅ 干净的 JAR,不含旧逻辑
操作结果
变化分析:
OldLogic.class和OldTest.txt等旧产物被彻底清除,不再污染新的构建产物- 打包的 JAR 只包含当前代码库中存在的类,消除了"已删代码幽灵般重现"的风险
- 小崔在团队内推广了"
mvn clean package组合命令"的最佳实践,前端黄俪和运维李眉也理解了为什么 CI/CD 流水线里总是先 clean 再构建 - 白歌在
pom.xml中增加了对logs/目录的清理配置,确保每次构建前日志文件也被重置
易错点与常见问题
误区一:clean 只是删除 target 目录
错误认知:"mvn clean 不就是 rm -rf target 吗?我自己手动删也一样。"
纠正:手动删除 target/ 确实能达到大部分效果,但 mvn clean 的价值在于:
- 可扩展性:通过
pom.xml配置,可以一并清理logs/、temp/、generated-sources/等其他目录 - 可移植性:Windows 上手动删是
rmdir /s /q target,Linux 上是rm -rf target,而mvn clean在任何平台都一样 - 可集成性:
pre-clean和post-clean阶段可以绑定自定义插件,实现"清理前自动备份""清理后发送通知"等自动化流程
误区二:clean 会删除本地仓库
错误认知:"mvn clean 会不会把我 ~/.m2/repository 里的依赖也删掉?那下次构建不是要重新下载?"
纠正:mvn clean 只删除项目目录下的 target/,绝不会触碰本地仓库 ~/.m2/repository。本地仓库里的依赖是跨项目共享的缓存,删除它们属于"自残"行为。如果你确实需要清理本地仓库(如某个依赖损坏),必须手动删除对应 GAV 路径下的目录,或者使用 mvn dependency:purge-local-repository 插件。
误区三:clean 生命周期会自动执行
错误认知:"我执行 mvn package,Maven 应该会先自动 clean 吧?不然旧产物不会干扰吗?"
纠正:mvn package 不会自动执行 clean。clean 和 default 是两个独立的生命周期,没有内置的触发关系。如果你需要"先清理再打包",必须显式执行 mvn clean package。很多新手在 IDE 里点"Rebuild Project"时,IDE 会隐式执行 clean,导致他们误以为 mvn package 也会自动清理。在 CI/CD 流水线中,忘记加 clean 是构建产物污染的常见原因。
小结
clean 生命周期是 Maven 三套生命周期中最简单、最直观的一套,由 pre-clean、clean、post-clean 三个阶段组成。clean 阶段通过 maven-clean-plugin 默认删除 target/ 目录,并支持通过 pom.xml 扩展清理范围。它的核心价值在于确保每次构建从零开始的环境纯净性,避免旧编译产物、旧测试报告、旧打包文件对新构建的干扰。
本章与全局的关系:本章讲解了"如何清理构建环境"。下一章"default 生命周期"将深入讲解 Maven 最核心的构建流水线——从 validate 到 deploy 的完整阶段链。