Maven 插件详解

官方原文

"Maven is - at its heart - a plugin execution framework; all work is done by plugins. Looking for a specific goal to execute? This page lists the core plugins and others. There are the build and the reporting plugins:

Build plugins will be executed during the build and they should be configured in the <build/> element from the POM.

Reporting plugins will be executed during the site generation and they should be configured in the <reporting/> element from the POM. Because the result of a Reporting plugin is part of the generated site, Reporting plugins should be both internationalized and localized."

—— Maven 官方文档


一、核心理解:Maven 的本质

Maven 本质上是一个插件执行框架;所有的工作都由插件完成。

这句话揭示了 Maven 的设计哲学:

说法 含义
"Maven 是插件执行框架" Maven 本身不实现任何构建功能,它只负责调度编排
"所有工作都由插件完成" 你做的所有操作——编译、测试、打包、部署——背后都是某个插件在执行
"寻找特定 Goal?" 如果你想知道某个任务怎么做,本质上是在找哪个插件的哪个 Goal

Maven 架构示意

┌──────────────────────────────────────────────────────────────┐
│                        Maven                                 │
│                    (插件执行框架)                            │
│                                                              │
│   ┌──────────────────────────────────────────────────────┐   │
│   │                    生命周期                           │   │
│   │    clean → compile → test → package → deploy        │   │
│   └──────────────────────────────────────────────────────┘   │
│                            │                                  │
│                            ▼                                  │
│   ┌──────────────────────────────────────────────────────┐   │
│   │                   插件执行器                          │   │
│   │    │          │            │          │             │   │
│   │    ▼          ▼            ▼          ▼             │   │
│   │ 编译插件   测试插件     打包插件   部署插件          │   │
│   └──────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────┘

二、插件的定义

2.1 通俗理解

Maven 本身只是一个骨架,它定义了生命周期(Lifecycle)——即构建项目要经历哪些阶段(编译、测试、打包、部署等),但它不干活,真正干活的是插件

可以把 Maven 比作一个流水线平台,插件就是工位上的工人

Maven 插件
定义构建流程(生命周期) 执行具体的构建任务
告诉你在哪个阶段做什么 负责实际把事情做出来
比如:package 阶段要打包 maven-jar-plugin 负责打出 JAR 包

2.2 官方定义

Maven 插件是一个或多个 Goal(目标) 的集合,每个 Goal 负责执行一个具体的构建任务。插件通过 Goal 绑定到生命周期的某个 Phase(阶段) 上执行。

  • Plugin(插件):一组功能的集合,提供多个 Goal
  • Goal(目标):插件中一个具体、可执行的原子操作

三、插件的两种类型

根据官方定义,Maven 插件分为两大类:

构建插件(Build Plugins) 报告插件(Reporting Plugins)
执行时机 构建生命周期中(compiletestpackage 等阶段) 生成站点文档时(mvn site
配置位置 <build><plugins> <reporting>
产出 构建产物(JAR、WAR、Docker 镜像等) 项目报告、文档(HTML 页面)
本地化要求 不需要 需要(面向用户阅读的报告)
示例 maven-compiler-plugindocker-maven-plugin maven-javadoc-pluginmaven-surefire-report-plugin

3.1 构建插件(Build Plugins)

官方定义"Build plugins will be executed during the build and they should be configured in the <build/> element from the POM."

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <source>17</source>
                <target>17</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>io.fabric8</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>0.43.4</version>
            <configuration>
                <images>
                    <image>
                        <name>myapp:${project.version}</name>
                        <build>
                            <contextDir>${project.basedir}</contextDir>
                        </build>
                    </image>
                </images>
            </configuration>
        </plugin>
    </plugins>
</build>

3.2 报告插件(Reporting Plugins)

官方定义"Reporting plugins will be executed during the site generation and they should be configured in the <reporting/> element from the POM. Because the result of a Reporting plugin is part of the generated site, Reporting plugins should be both internationalized and localized."

<reporting>
    <plugins>
        <!-- JavaDoc 报告(支持多语言) -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>3.5.0</version>
            <configuration>
                <aggregate>true</aggregate>
                <locale>zh_CN</locale>  <!-- 本地化:中文 -->
            </configuration>
        </plugin>
        <!-- 单元测试报告 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <version>3.0.0-M9</version>
            <configuration>
                <locale>zh_CN</locale>
            </configuration>
        </plugin>
    </plugins>
</reporting>

3.3 两种插件的对比图解

Maven 构建生命周期                           Maven Site 生命周期
─────────────────────                      ────────────────────

compile  ──▶ maven-compiler-plugin         pre-site
   │                                          │
test    ──▶ maven-surefire-plugin          site  ──▶ 报告插件生成报告
   │                                          │
package ──▶ maven-jar-plugin              post-site
   │                                          │
deploy  ──▶ maven-deploy-plugin            site-deploy

     ▲                                              ▲
     │                                              │
 构建插件(Build Plugins)                    报告插件(Reporting Plugins)
 产出:JAR/WAR/Docker 镜像                    产出:HTML 文档/报告

四、插件的组成结构

每个插件由三部分组成:

<plugin>
    <groupId>io.fabric8</groupId>                 <!-- 组织ID -->
    <artifactId>docker-maven-plugin</artifactId> <!-- 插件ID -->
    <version>0.43.4</version>                     <!-- 版本 -->
    <configuration>...</configuration>            <!-- 配置 -->
    <executions>...</executions>                  <!-- 执行绑定 -->
</plugin>
  • 坐标(GAV):Maven 用来下载和识别插件的唯一标识
  • Goal:插件提供的具体功能,如 docker:builddocker:push
  • 配置:定制插件的行为
  • 执行绑定:将特定 Goal 绑定到生命周期的某个阶段

五、执行插件的方式

方式一:通过命令行直接调用

# 格式:mvn 插件前缀:目标
mvn docker:build          # 构建镜像
mvn docker:push           # 推送镜像

mvn spring-boot:run       # 运行 Spring Boot 应用
mvn clean:clean           # 清理

方式二:绑定到生命周期自动执行

<plugin>
    <executions>
        <execution>
            <phase>install</phase>          <!-- 在 install 阶段执行 -->
            <goals>
                <goal>build</goal>           <!-- 执行 build 目标 -->
            </goals>
        </execution>
    </executions>
</plugin>

这样当运行 mvn install 时,docker:build 会被自动执行。

方式三:使用完整坐标调用

# 格式:mvn groupId:artifactId:version:goal
mvn io.fabric8:docker-maven-plugin:0.43.4:build

六、插件前缀与完整坐标

Maven 通过插件前缀简化命令,前缀映射在插件的 META-INF/maven/plugin.xml 中定义:

简写命令 实际执行的完整坐标 说明
mvn docker:build mvn io.fabric8:docker-maven-plugin:0.43.4:build 使用前缀 docker
mvn spring-boot:run mvn org.springframework.boot:spring-boot-maven-plugin:run 使用前缀 spring-boot
mvn compiler:compile mvn org.apache.maven.plugins:maven-compiler-plugin:compile 核心插件前缀

settings.xml 中的 <pluginGroups> 可以自定义前缀:

<settings>
    <pluginGroups>
        <pluginGroup>io.fabric8</pluginGroup>
        <pluginGroup>org.springframework.boot</pluginGroup>
    </pluginGroups>
</settings>

七、插件与依赖的区别

插件 (Plugin) 依赖 (Dependency)
作用时机 构建时执行 编译/运行时使用
用途 执行构建任务(编译、打包、测试等) 提供代码所需的功能库
产物 不进入最终应用包 被打入最终应用包
位置 <build><plugins><reporting> <dependencies>

简单说:依赖是给代码用的,插件是给构建过程用的。


八、常见插件分类

分类 插件示例 用途 类型
编译构建 maven-compiler-plugin 编译 Java 代码 Build
打包 maven-jar-pluginmaven-war-plugin 打包 JAR/WAR Build
测试 maven-surefire-plugin 运行单元测试 Build
容器化 docker-maven-plugin 构建 Docker 镜像 Build
文档 maven-javadoc-plugin 生成 JavaDoc Reporting
测试报告 maven-surefire-report-plugin 生成测试报告 Reporting
代码质量 maven-pmd-pluginspotbugs-maven-plugin 静态代码检查 Reporting/Build
发布部署 maven-deploy-plugin 部署到仓库 Build

九、为什么"所有工作都由插件完成"

这个设计哲学解释了三个关键现象:

  1. 为什么 Maven 不需要安装"功能模块"?
  • 插件是按需下载的,用的时候才从 Maven 仓库拉取
  1. 为什么 Maven 可以无限扩展?
  • 任何人都可以编写 Maven 插件,没有功能边界
  1. 为什么 Maven 说"不够用就自己写插件"?
  • 因为这就是它的核心设计模式

十、总结

关键点 说明
Maven 的本质 插件执行框架,自身不干活
构建插件 配置在 <build>,在构建生命周期中执行,产出代码产物
报告插件 配置在 <reporting>,在站点生成时执行,产出文档报告
Goal 插件中最小的执行单元,如 docker:build
执行方式 命令行直接调用 / 绑定生命周期 / 完整坐标调用
与依赖的区别 插件给构建用,依赖给代码用

一句话总结Maven 只是一个"导演"(插件执行框架),自己不干活,所有"演员"(插件)完成具体工作;构建插件在编译打包时出场(产出代码产物),报告插件在生成文档时出场(产出项目报告)。


参考链接
- Maven 官方插件列表
- Maven 插件开发指南