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 編寫插件的主要步驟
- 創建 maven-plugin 項目: 其實也是創建一個 Maven 項目,只不過 pom.xml 文件中的 packaging 必須為 maven-plugin;
- 編寫插件目標: 通常情況下,一個插件會有一個或者多個目標,即一個或者多個 Mojo 。而這個 Mojo 類必須要繼承 AbstractMojo 類;
- 為目標提供配置點: 通常情況下 Maven 插件的目標都是可配置的,所以我們在編寫插件的時候,也盡量需要提供可配置的參數;
- 實現目標行為: 一個繼承了 AbstractMojo 的 Mojo 類,需要實現其中的 excute 方法,這個方法即是插件目標要做的事情;
- 記錄日志并處理異常: 如同編寫其他的程序一樣,編寫插件的時候,也需要通過記錄日志的方式來記錄插件的運行狀態;
- 測試并運行插件: 插件編寫完成后,我們要對插件進行簡單的測試,并通過實際運行插件的方式來驗證插件是否能夠滿足我們的要求。
從上面的步驟來看,其實編寫插件也就相當于編寫一個小型的項目,從創建項目到開發,測試再到上線發布,每一個步驟都需要經過。
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 提供的插件不能滿足我們需求的時候,就可以嘗試去自定義一個簡單插件來供自己使用。