Maven 编写插件

这一节我们来讲如何编写 Maven 的插件。在生命周期一节中,我们了解到一个插件通常是包含多个目标的,而不同的目标也就对应了生命周期中的不同阶段。在之前的章节中,我们着重介绍如何使用 Maven 的插件,那么在本节中,我们来介绍如何自定义一个插件。其实通常情况下,我们是不需要自己定制插件的,因为 Maven 有太多可以配置的插件供开发者来使用的,所以,除非一个开发者发现自己有非常特殊的需求,而这个需求并不能通过现有的插件来完成的时候,才需要自定义一个 Maven 插件了。

图片描述

1. 什么是插件

在编写插件之前,我们先来看看什么是 Maven 插件。

1.1 控制反转

类似于 Spring 框架的 Ioc 容器,Maven 也沿用了这种做法,将其中与生命周期进行绑定的 Mojo Bean 进行托管,将对象的创建和控制权交与 Ioc 容器来进行管理。在 Ioc 容器中比较重要的一个概念就是依赖注入,在 Maven 编程的时候,会使用到两种依赖注入方式:

  • 构造器注入: 即在对象被创建的时候,通过构造器参数,将对象的值传入并赋值;
  • set 方法注入: 即通过对象属性的 set 方法来为对象的属性赋值。

总的来讲,在 Maven 中实现的 Ioc 容器和 Spring 中的 Ioc 容器是非常类似的。

1.2 Mojo

通常情况下,Maven 插件包括不同的目标,而这些目标则是通过 Mojo 来实现的。Mojo 可以对标 Java 中的 Pojo,这样理解起来就会很方便。而这些 Mojo 对象则是被 Maven 中的 Ioc 容器进行管理的。

例如, install:install 目标对应 Maven Install 插件中的 InstallMojo 的 Java 类。而 deploy:deploy目标则对应 Maven Deploy 插件中的 DeployMojo 的 Java 类。

1.3 插件描述符

在 Maven 插件的 JAR 文件中,有一个 META-INF/maven/plugin.xml 配置文件,这个文件描述了这个插件中的各个 Mojo 对象与其他的插件配置(我们可以在本地仓库中找到任何一个插件,来查看该插件的 plugin.xml 文件)。当一个插件的被添加到依赖中的时候,Maven 会首先去读取这个文件,来对该插件进行初始化。通常,这个文件并不需要我们自己来编写,而是在生成插件的时候,Maven 会帮我们来完成。

2. 编写插件

2.1 编写插件的主要步骤

  1. 创建 maven-plugin 项目: 其实也是创建一个 Maven 项目,只不过 pom.xml 文件中的 packaging 必须为 maven-plugin;
  2. 编写插件目标: 通常情况下,一个插件会有一个或者多个目标,即一个或者多个 Mojo 。而这个 Mojo 类必须要继承 AbstractMojo 类;
  3. 为目标提供配置点: 通常情况下 Maven 插件的目标都是可配置的,所以我们在编写插件的时候,也尽量需要提供可配置的参数;
  4. 实现目标行为: 一个继承了 AbstractMojo 的 Mojo 类,需要实现其中的 excute 方法,这个方法即是插件目标要做的事情;
  5. 记录日志并处理异常: 如同编写其他的程序一样,编写插件的时候,也需要通过记录日志的方式来记录插件的运行状态;
  6. 测试并运行插件: 插件编写完成后,我们要对插件进行简单的测试,并通过实际运行插件的方式来验证插件是否能够满足我们的要求。

从上面的步骤来看,其实编写插件也就相当于编写一个小型的项目,从创建项目到开发,测试再到上线发布,每一个步骤都需要经过。

2.2 编写插件案例

那接下来,我们就实际编写一个小插件来进行演示。

首先,我们在存放代码的目录下执行命令 mvn archetype:generate (在 idea 中根据 archetype 来创建项目,效果相同),选择 maven-archetype-plugin 模板,然后依次按照提示输入 groupId 和 artifactId 等等信息。

这里,我们为这个插件命名为 my-plugin,项目结构如下:

接下来,我们就创建一个自己的 Mojo 类,叫做 SumFileMojo,这个目标用于统计当前项目中有多少个Java 类。并且,我们将原本的 MyMojo 类删掉。

package com.mic.tech;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.File;
import java.util.Objects;

/**
 * @Auther: Uncle Biao
 * @Date: 2020/6/9 23:37
 * @Description:
 */
@Mojo(name = "sumFileCount",defaultPhase= LifecyclePhase.COMPILE)
public class SumFileCountMojo extends AbstractMojo {

    @Parameter(property = "path")
    private String path;
    /**
     * java文件数量
     */
    int javaFileCount = 0;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println(countJavaFile(path));
    }

    public String countJavaFile(String path){
        File file = new File(path);
        if (file.exists()) {
            File [] files = file.listFiles();
            if(Objects.isNull(files)){
                for(int i=0 ; i < files.length ; i++){
                    File currentFile = files[i];
                    if(currentFile.isFile()){
                        String fileName = currentFile.getName();
                        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
                        if("java".equals(suffix)){
                            javaFileCount ++;
                        }
                    }else{
                        countJavaFile(currentFile.getAbsolutePath());
                    }
                }
            }
        }
        return "number of Java File is " + javaFileCount;
    }
}

编码完成后,我们执行 mvn clean install 命令将插件构建到本地仓库中去。

接下来,我们可以在 mall 项目中加入该插件的依赖,并且为该插件配置执行目标。

<plugin>
    <groupId>com.mic.tech</groupId>
    <artifactId>my-plugin</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <configuration>
  	  <path>${project.basedir}</path>
    </configuration>
    <executions>
        <execution>
            <phase>compile</phase>
            <goals>
            	<goal>sumFileCount</goal>
            </goals>
        </execution>
    </executions>
</plugin>

依赖添加完成后,在 mall-order 模块下执行命令 mvn compile 便可以看到统计出来 Java 文件的数量。

至此,我们编写了一个简单的插件,用于统计项目中 Java 文件的数量。

3. 小结

本节中,我们介绍了如何自定义一个 Maven 插件,需要注意的地方,以及通常的编写步骤。最后,我们编写了一个用于统计项目中 Java 文件数量的插件。当 Maven 提供的插件不能满足我们需求的时候,就可以尝试去自定义一个简单插件来供自己使用。