Gradle學(xué)習(xí)7——編寫和使用自定義Task

學(xué)習(xí)本系列前可以下載相關(guān)的github項(xiàng)目gradleLearnDemo。
地址:https://github.com/sososeen09/gradleLearnDemo

自定義task包含兩個(gè)組件:
1)自定義的task類,封裝了邏輯行為,也被稱作任務(wù)類型
2)真實(shí)的task,提供了用于配置行為的task類所暴露的屬性值。Gradle把這些task稱為增強(qiáng)的task。

可維護(hù)性是編寫自定義task類的優(yōu)勢之一。增強(qiáng)的task的另一個(gè)優(yōu)勢是可重用性。自定義task所暴露的屬性可以在構(gòu)建腳本中進(jìn)行單獨(dú)設(shè)置。

我們還是按照之前的例子,修改配置文件中的release 參數(shù)。

1 自定義task類

前面已經(jīng)提到,Gradle為構(gòu)建腳本中每個(gè)簡單的task都創(chuàng)建了一個(gè)DefaultTask類型的實(shí)例。我們現(xiàn)在創(chuàng)建一個(gè)ReleaseVersionTask,它的作用是把目標(biāo)文件中的release變?yōu)閠rue。

class ReleaseVersionTask extends DefaultTask{
  @Input Boolean release
  @OutputFile File destFile

  ReleaseVersionTask(){
    group='versioning'
    description='Makes project a release version.'
  }

  @TaskAction
  void start(){
    project.version.release=true;
    ant.propertyfile(file:destFile){
       entry(key:'release',type:'string',operation:'=',value: 'true')
    }
  }
}

通過org.gradle.api.tasks包下的注解可以用來聲明輸入輸出屬性。

task輸入驗(yàn)證 @Input注解會(huì)在配置期間驗(yàn)證屬性值。如果值為null,Gradle會(huì)拋出TaskValidationException異常。為了允許輸入為null值,可以給它添加@Optional注解。

2 使用自定義task

我們自定義的task類是沒有辦法自己執(zhí)行的,要使用和配置自定義task類定義的行為和屬性,需要?jiǎng)?chuàng)建一個(gè)增強(qiáng)型的task。該task定義了它要使用的task類型,在本例中我們定義一個(gè)增強(qiáng)型taskmakeReleaseVersion,它使用的task類型是ReleaseVersionTask,通過為它的屬性賦值來設(shè)置輸入和輸出。

task makeReleaseVersion(type:ReleaseVersionTask){
// 設(shè)置自定義task屬性
    release = version.release
    destFile = versionFile
}

執(zhí)行 gradle makeReleaseVersion 命令 ,會(huì)發(fā)現(xiàn)增強(qiáng)型的makeReleaseVersion task與之前的文章中簡單的task的運(yùn)行結(jié)果表現(xiàn)完全一致。
與簡單的task實(shí)現(xiàn)相比,增強(qiáng)型task的一個(gè)巨大優(yōu)勢在于所暴露的屬性可以被單獨(dú)賦值。

比如,ProjectVersion 中的release字段名改為了prodReady,屬性文件改名為 project-version.properties。
那么makeReleaseVersion task可以這樣設(shè)置

task makeReleaseVersion(type:ReleaseVersionTask){
    release = version.prodReady
    destFile =file('project-version.properties')
}

3 在buildSrc目錄下構(gòu)建代碼

我們可以把ReleaseVersionTask這個(gè)類單獨(dú)放在一個(gè)Groovy文件中,這樣就可以在其它地方通過導(dǎo)包的方式來重用這個(gè)類。
在一個(gè)項(xiàng)目工程當(dāng)中,創(chuàng)建的Groovy類適合被移動(dòng)到項(xiàng)目的buildSrc目錄下。Gradle在buildSrc目錄下使源文件結(jié)構(gòu)標(biāo)準(zhǔn)化。Groovy代碼放在src/main/groovy目錄下,對(duì)于Java文件則是放置在src/main/java目錄下面。位于這些目錄下的文件會(huì)被自動(dòng)編譯,并且都加入到Gradle構(gòu)建腳本的classpath中。

注意:提取一個(gè)類到Groovy文件中需要設(shè)置package,在build.gradle中或者其它地方使用這個(gè)類的時(shí)候需要導(dǎo)包,這一點(diǎn)與Java類的使用是一樣的。當(dāng)然了,如果這個(gè)類本身就放在build.gradle中則不需要這個(gè)過程,就像之前的例子那樣。

例如 ReleaseVersionTask

package com.sososeen09.gia

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
class ReleaseVersionTask extends DefaultTask{
...
}

Groovy文件實(shí)際放置的位置是 buildSrc/src/main/groovy/com/sososeen09/gia/ReleaseVersionTask

根據(jù)同樣的方式,我們也可以把ProjectVersion這個(gè)類抽取出來。

使用的時(shí)候,在build.gradle中頂部記得導(dǎo)包:

import com.sososeen09.gia.ReleaseVersionTask
import com.sososeen09.gia.ProjectVersion
...

此時(shí),執(zhí)行gradle makeReleaseVersion 命令,我們就可以看到編譯過程:

:buildSrc:compileJava UP-TO-DATE
:buildSrc:compileGroovy UP-TO-DATE
:buildSrc:processResources UP-TO-DATE
:buildSrc:classes UP-TO-DATE
:buildSrc:jar UP-TO-DATE
:buildSrc:assemble UP-TO-DATE
:buildSrc:compileTestJava UP-TO-DATE
:buildSrc:compileTestGroovy UP-TO-DATE
:buildSrc:processTestResources UP-TO-DATE
:buildSrc:testClasses UP-TO-DATE
:buildSrc:test UP-TO-DATE
:buildSrc:check UP-TO-DATE
:buildSrc:build UP-TO-DATE
Reading the version file
:makeReleaseVersion

記?。篵uildSrc 目錄被視為Gradle項(xiàng)目的指定路徑。

4 把Task編寫的類編譯成jar包提供給其它項(xiàng)目使用

我們把Groovy類放在了buildSrc目錄下,雖然自定義的Task類與build.gradle分離開了,但是這些類依然只能應(yīng)用到當(dāng)前的項(xiàng)目中。如果我們想要在其它的項(xiàng)目中也可以使用這些Task,就需要在單獨(dú)的項(xiàng)目中來定義,然后其它項(xiàng)目通過聲明依賴的方式來使用。

創(chuàng)建一個(gè)新項(xiàng)目,把之前我們講的buildSrc目錄下的內(nèi)容復(fù)制到這個(gè)項(xiàng)目中。這個(gè)時(shí)候,我們就要自己使用Groovy插件來編譯這些Groovy源代碼了,就像我們編譯Java代碼需要Java插件一樣。Groovy插件是基于Java插件的。在這個(gè)項(xiàng)目目錄下新建一個(gè)build.gradle文件,并在文件中引入Groovy Plugin。
還有一點(diǎn),我們期望把這些Groovy編寫的Task和其它類打包成jar文件供其它地方使用。這個(gè)時(shí)候我們就可以使用maven插件,把jar文件上傳到repository中。關(guān)于如何使用maven插件上傳,可以查閱相關(guān)文檔,也可以看這篇 Gradle User Guide Maven Plugin。為了簡單演示,打包的jar文件上傳到了本地的文件系統(tǒng)中。最終的build.gradle文件如下:

apply plugin: 'groovy' 
apply plugin: 'maven'

version = '1.0'
group = 'com.sososeen09.gia'
archivesBaseName = 'releaseVersionTask'

repositories {
    mavenCentral()
}

dependencies {
    // 編譯的時(shí)候我們需要使用Gradle中的API
    compile gradleApi()
}

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: "file:../lib")
        }
    }
}

執(zhí)行gradle uploadArchives命令后就可以看到,在與當(dāng)前項(xiàng)目同級(jí)的lib文件目錄中生成了我們期望的jar文件。

下面來演示如何使用這個(gè)jar文件。我們?cè)傩陆ㄒ粋€(gè)工程,這個(gè)工程中有一個(gè)腳本文件build.gradle和一個(gè)配置文件version.properties。
其中,build.gradle中的代碼如下:

import com.sososeen09.gia.ReleaseVersionTask
import com.sososeen09.gia.ProjectVersion
buildscript {
    repositories {
        maven {
            url 'file:../lib'
        }

    }

    dependencies {
        classpath 'com.sososeen09.gia:releaseVersionTask:1.0'
    }
}

version=new ProjectVersion(0,1)

task printVersion {
  doLast{
    logger.quiet "Version: $version"
  }
}

// Project接口提供了file方法,它會(huì)創(chuàng)建一個(gè)相對(duì)于項(xiàng)目目錄的java.io.File實(shí)例
ext.versionFile=file('version.properties')

task loadVersion{
    project.version=readVersion()
}

//readVersion方法,與task是不同的
ProjectVersion readVersion(){
    logger.quiet 'Reading the version file'
    if(!versionFile.exists()){
        throw new GradleException ("Required version file dose not exist:$versionFile.canonicalPath " )
    }

    //Groovy的文件實(shí)現(xiàn)通過添加新的方法來讀取InputStream
    Properties versionProps=new Properties()
    versionFile.withInputStream{stream->
        versionProps.load(stream)
    }
    // 在Groovy中,如果return是方法中的最后一條語句的話,則可以將它省略
    new ProjectVersion(versionProps.major.toInteger(),versionProps.minor.toInteger(),versionProps.release.toBoolean())
}


task makeReleaseVersion(type:ReleaseVersionTask){
    release = version.release
    destFile = versionFile
}

version.properties中的內(nèi)容如下:

major=0
minor=1
release=fasle

執(zhí)行 gradle makeReleaseVersion 命令之后可以看到配置文件中release變?yōu)閠rue。

5 總結(jié)

通過以上的介紹,我們了解了自定義Task的方式。 自定義的Task可以放置在build.gradle腳本中,也可以在當(dāng)前的項(xiàng)目的buildSrc目錄下。當(dāng)然了,如果你期望你寫的自定義Task可以被其它的項(xiàng)目中使用,那么你可以用一個(gè)單獨(dú)的工程來放置自定的Task。

關(guān)于自定義Task的學(xué)習(xí),我們也可以查看Gradle的官方Guide來查看如何自定義task

下一篇,我們開始學(xué)習(xí)Gradle中的依賴管理。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,993評(píng)論 19 139
  • 這篇文章講給大家?guī)韌radle打包系列中的高級(jí)用法-自己動(dòng)手編寫gradle插件。我們平常在做安卓開發(fā)時(shí),都會(huì)在...
    呆萌狗和求疵喵閱讀 16,032評(píng)論 22 80
  • 1. 概述 Android項(xiàng)目的構(gòu)建過程是由Gradle插件完成的,Gradle 插件是在Gradle框架的基礎(chǔ)上...
    小蕓論閱讀 8,225評(píng)論 1 42
  • 導(dǎo)語: 隨著技術(shù)的發(fā)展,不管是前端開發(fā)、服務(wù)端開發(fā)或者是移動(dòng)端開發(fā)(移動(dòng)也是前端的一個(gè)分支)中都會(huì)用到自動(dòng)化構(gòu)建工...
    伊始雨深閱讀 3,058評(píng)論 0 4
  • 多久沒有安靜下來,記錄這自己的內(nèi)心。一切都是安安靜靜、如此淡然。 也許是忘性大,也許是沒有心,總是這...
    盧新莎子閱讀 274評(píng)論 0 0