使用 Java 開發 Gradle 外掛

Robothy發表於2021-03-03

Gradle 外掛程式碼可以在 build.gradle 中,buildSrc 專案中,以及獨立的外掛專案中編寫。本文將介紹如何在一個獨立的專案中使用 Java 語言編寫 Gradle 外掛,併發布到倉庫中。

1 建立專案

Gradle 外掛專案和普通的 Java 專案沒有什麼不同,普通專案是基於其它三方包進行開發,而 Gradle 外掛專案基於 Gradle 的 API 進行開發。

基於 Gradle 建立一個 Java 專案,專案目錄結構如下,和普通專案一樣。示例專案:https://github.com/Robothy/gradle-plugin-sample

gradle-plugin-sample
|
├───build.gradle
├───settings.gradle
└───src
    ├───main
    │   ├───java
    │   └───resources
    └───test
        ├───java
        └───resources

引入 Gradle API 相關的 jar 包。為了方便起見,可以通過 gradle 外掛 java-gradle-plugin 來引入 Java 外掛,引入 Gradle API 相關依賴以及生成外掛相關的描述符。

build.gradle

plugins {
    id 'java-gradle-plugin'
}

group 'com.robothy'
version '1.0-SNAPSHOT'

repositories {
    mavenLocal()
    mavenCentral()
}

wrapper{
    gradleVersion = '6.7'
}

2 動手開發

專案建立好之後,就可以開始動手開發了。從專案構建角度來看,Gradle 外掛是一段可重用的構建邏輯,這段邏輯能夠被應用到各個專案當中。更具體來說,Gradle 外掛是一個實現了 org.gradle.api.Plugin 介面的類,它被 Project (可以認為是 build.gralde, 它本質是一個實現了 Project 介面的類)所引用。開發外掛的本質就是往 build.gradle 中插入一段邏輯。

void apply​(T target)

Plugin 是一個泛型介面,有一個抽象方法 apply,它的引數型別可以是 Project, Settings, 或者 Gradle

  • 型別為 Project,外掛可以應用於 build.gradle;

  • 型別為 Settings,外掛可應用於 settings.gradle;

  • 型別為 Gradle, 外掛可應用於 Gradle 初始化指令碼。

在應用外掛時,gradle 會建立一個外掛類的例項,並呼叫 apply 方法。因此,外掛的邏輯就是 apply 方法中的程式碼。

一個獨立的專案中可以有多個實現了 Plugin 介面的類,意味著一個專案可以包含多個外掛。每一個外掛都需要在 build.gradle 中新增相應的描述,java-gradle-plugin 會根據這些描述生成外掛描述符(jar 包中的一個檔案)。

假設要在 gradle-plugin-sample 專案中建立兩個外掛 hello, goodbye,需要進行如下兩個步驟:

1)建立外掛類

HelloPlugin.java

import org.gradle.api.Plugin;
import org.gradle.api.Project;

public class HelloPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        System.out.println("Message from hello plugin.");
    }
}

GoodbyePlugin.java

import org.gradle.api.Plugin;
import org.gradle.api.Project;

public class GoodbyePlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        System.out.println("Message from goodbye plugin.");
    }
}

2)在 build.gradle 中新增描述內容

描述內容需要指定外掛的 ID 和外掛的入口類。

gradlePlugin {
    plugins {
        helloPlugin {
            id = 'com.robothy.hello'
            implementationClass = 'com.robothy.HelloPlugin'
        }
        googbyePlugin{
            id = 'com.robothy.goodbye'
            implementationClass = 'com.robothy.GoodbyePlugin'
        }
    }
}

完成上面步驟之後,一個簡單的外掛就算完成了開發,接下來就可以釋出和使用了。

3 釋出外掛

外掛可以釋出到 Maven 倉庫和 Gradle 官方外掛門戶。

3.1 釋出到 Maven 倉庫

釋出外掛到 Maven 倉庫和釋出普通的 jar 包一樣,需要用到 maven-publish 外掛。要釋出到遠端 Maven 倉庫可能需要提供認證資訊,這裡簡單起見只發布到本地倉庫。

1)在 build.gradle 檔案中新增 maven-publish 外掛

plugins {
    id 'java-gradle-plugin'
    id 'maven-publish'
}

2)執行 gradle publishToMavenLocal,成功之後可以在 ~/.m2 目錄下找打發布的 jar 包。

要使用釋出到 Maven 倉庫中的 Gradle 外掛,需要先在 settings.gradle 中指定倉庫。如下程式碼指定了外掛倉庫有本地 Maven 和 Gradle 外掛門戶。

pluginManagement {
    repositories {
        mavenLocal()
        gradlePluginPortal()
    }
}

3.2 釋出到 Gradle 官方外掛門戶

我們平常使用的大部分外掛來自於 Gradle 官方外掛門戶,開發人員註冊一個 Gradle 賬號之後可以將外掛釋出到門戶,這樣其他人就可以很方便地使用了。按照如下步驟釋出外掛,這裡如果沒有描述清楚可以移步 Gradle 官網文件:How do I add my plugin to the plugin portal?

1)註冊門戶賬戶

2)建立 API Key。註冊好賬戶就能夠看見了。

3)將 API Key 新增到檔案 ~/.gradle/gradle.properties

4)使用外掛釋出外掛 com.gradle.plugin-publish 釋出外掛(不是病句,只是有點繞 ?)

將 com.gradle.plugin-publish 新增到外掛專案 gradle-plugin-sample 的 build.gradle 中,然後新增外掛的描述資訊。

pluginBundle {
  website = 'http://www.gradle.org/'
  vcsUrl = 'https://github.com/gradle/gradle'
  description = 'Greetings from here!'
  tags = ['greetings', 'salutations']

  plugins {
    greetingsPlugin {
      // id='com.robothy.hello' 可以省略,因為在 gradlePlugin 配置塊中已經有 id 資訊了
      displayName = 'Hello Plugin'
    }
  }
}

5)使用 gradle publishPlugins 釋出外掛

如果外掛資訊描述正確,執行 puhlishPlugins 任務之後會列印出待稽核的資訊,之後就是等待了(本人釋出的外掛 com.robothy.cn-repo 經過了四五個小時就稽核通過了)。

Publishing plugin com.robothy.cn-repo version 1.0
Thank you. Your new plugin com.robothy.cn-repo has been submitted for approval by Gradle engineers. The request should be processed within the next few days, at which point you will be contacted via email.

4 更多

4.1 在外掛中新增任務

先自定義一個 Gradle 任務類 SayHelloTask,該任務的行為是簡答的列印固定的字串。自定義任務需要繼承 DefaultTask。

public class SayHelloTask {
    @TaskAction
    public void hello() {
        System.out.println("Hello, World!");
    }
}

然後通過 project 往專案中註冊一個 SayHelloTask 的例項,任務名為 task。

public class HelloPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        System.out.println("Message from hello plugin.");
        project.getTasks().register("hello", SayHelloTask.class);
    }
}

當然,也可以在使用 HelloPlugin 外掛的 build.gradle 中註冊任務。

task hello(type: com.robothy.SayHelloTask)

重新發布外掛,執行下面命令時控制檯會列印出 "Hello, World!"。

gradle hello

4.2 新增擴充套件

Gradle 外掛可以往 project 中註冊擴充套件,開發人員可以通過擴充套件設定一些引數值,以供其它的 Gradle Task 使用。假設我們希望在 build.gradle 中新增如下配置資訊。

user {
    name = 'Robothy'
    country = 'China'
}

首先,建立一個配置資訊介面,介面中只包含 getter 抽象方法。需要注意的是,返回的型別為 Property,並非直接返回 String。配置資訊不需要建立為 Java 類,Gradle 在執行時會通過動態代理的方式自動往代理物件中注入值。

public interface User {
    Property<String> getName();
    Property<String> getCountry();
}

然後外掛就可以往 project 中新增一個擴充套件了。

project.getExtensions().add("user", User.class);

重新發布外掛,此時引入了外掛的專案就可以在 builde.gradle 中新增本小節開頭描述的配置塊了。

Gradle 任務可以通過如下方式訪問到這些配置資訊。

User user = (User) (project.getExtensions().getByName("user"));

5 小結

本文主要介紹瞭如何使用純 Java 語言在一個獨立的專案中編寫 Gradle 外掛,外掛主要通過通過傳入的 project 引數訪問專案,往專案的構建生命週期中插入一些邏輯或者新增配置資訊。外掛可以釋出到私有的 Maven 倉庫,也可以釋出到 Gradle 外掛門戶。外掛專案中還可以很好地封裝一些 Gradle Task,定義一些配置型別。

6 參考內容

[1] Build Script Basics

[2] How do I add my plugin to the plugin portal?

[3] Developing Custom Gradle Plugins

相關文章