Maven 生命周期与插件机制详解
Maven 的生命周期定义了构建的阶段流程,插件定义了每个阶段做什么。理解"生命周期 → 阶段 → 插件目标"三层结构,就能精确控制任意构建行为。
三套生命周期
Maven 内置三套相互独立的生命周期:
| 生命周期 | 用途 |
|---|---|
| clean | 清理构建产物 |
| default | 核心构建(编译、测试、打包、安装、部署) |
| site | 生成项目站点文档 |
三套生命周期相互独立:执行 mvn clean install 实际上是先跑 clean 生命周期的 clean 阶段,再跑 default 生命周期的 install 阶段。
clean 生命周期
pre-clean → clean → post-clean只有 3 个阶段,clean 阶段删除 target/ 目录。
site 生命周期
pre-site → site → post-site → site-deploysite 生成项目文档,site-deploy 部署到远程。
default 生命周期
default 生命周期是核心,共有 20+ 个阶段,按顺序执行:
validate 验证项目配置正确性
initialize 初始化构建状态(创建目录等)
generate-sources 生成源代码
process-sources 处理源代码
generate-resources 生成资源文件
process-resources 复制资源到 target/classes
compile 编译主源码到 target/classes
process-classes 处理编译产物
generate-test-sources 生成测试源码
process-test-sources 处理测试源码
test-compile 编译测试代码
process-test-classes 处理测试编译产物
test 运行单元测试
prepare-package 打包前准备
package 打包(jar/war)
pre-integration-test 集成测试前准备
integration-test 运行集成测试
post-integration-test 集成测试后清理
verify 校验包质量
install 安装到本地仓库 ~/.m2/repository
deploy 部署到远程仓库阶段执行规则
执行某阶段时,其之前的所有阶段都会依次执行:
bash
mvn package # validate → ... → package
mvn install # 全流程 + install
mvn deploy # 全流程 + install + deploy因此 mvn install 必然包含 mvn test、mvn package 的全部动作,无需重复执行。
插件与目标(Plugin & Goal)
阶段本身不执行任何逻辑,真正干活的是插件。每个插件包含一个或多个目标(Goal):
插件:maven-compiler-plugin
└── 目标:compile(编译主代码)、testCompile(编译测试代码)| 插件 | 目标 | 说明 |
|---|---|---|
| maven-compiler-plugin | compile / testCompile | 编译 |
| maven-surefire-plugin | test | 运行测试 |
| maven-jar-plugin | jar | 打包 jar |
| maven-install-plugin | install | 安装本地仓库 |
| maven-deploy-plugin | deploy | 部署远程 |
阶段与目标绑定
Maven 默认把常用插件的目标绑定到 default 生命周期的特定阶段,所以 mvn package 能直接完成编译、测试、打包。
默认绑定表(jar 打包)
| 阶段 | 默认绑定目标 |
|---|---|
| process-resources | resources:resources |
| compile | compiler:compile |
| process-test-resources | resources:testResources |
| test-compile | compiler:testCompile |
| test | surefire:test |
| package | jar:jar |
| install | install:install |
| deploy | deploy:deploy |
自定义绑定
在 <executions> 中把插件的目标绑定到任意阶段:
xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.1</version>
<executions>
<!-- 把 jar-no-fork 目标绑定到 package 阶段 -->
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build><phase> 指定绑定的阶段,<goals> 声明要执行的目标,<id> 区分同一插件的多个 execution。
命令行直接调用目标
阶段之外,插件目标也可以直接执行(无需经过生命周期):
bash
mvn compiler:compile # 直接调用 compiler 插件 compile 目标
mvn dependency:tree # 查看依赖树
mvn help:effective-pom # 查看有效 POM
mvn release:prepare # release 插件语法为 插件前缀:目标,Maven 通过插件前缀(如 dependency)查找对应的插件 groupId/artifactId。
插件版本与配置
版本管理
插件本身也是构件,有版本。推荐在 <pluginManagement> 中统一管理:
xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>配置作用域
插件 <configuration> 可以在插件声明或 execution 中配置:
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source> <!-- 插件级:所有 execution 生效 -->
<target>21</target>
</configuration>
</plugin>常见问题
mvn test会触发 compile 吗? 会。test 阶段之前有 compile、test-compile,会一并执行。- 跳过测试的三种方式?
-DskipTests(编译测试但不运行)、-Dmaven.test.skip=true(连测试代码都不编译)、surefire 插件skip配置。 - 自定义目标绑定到哪个阶段? 参考阶段语义:资源处理绑 process-resources、代码生成绑 generate-sources、打包后处理绑 package 之后。
- 怎么查看一个阶段绑定了哪些目标?
mvn help:describe -Dcmd=compile查看某命令对应的插件与目标。