在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 物聯(lián)網(wǎng)/ 任務(wù)詳述
問題反饋
Gradle 插件
Scala 插件
Gradle 命令行的基本使用
任務(wù)詳述
安裝
概述
教程-雜七雜八
構(gòu)建環(huán)境
依賴管理基礎(chǔ)
使用 Gradle 圖形用戶界面
使用文件
CodeNarc 插件
Sonar 插件
Groovy 插件
Sonar Runner 插件
OSGi 插件
Ear 插件
Gradle 守護(hù)進(jìn)程
Java 插件
簡介
構(gòu)建基礎(chǔ)
FindBugs 插件
Groovy 快速入門
JaCoCo 插件
PMD 插件
War 插件
Checkstyle 插件
日志
Java 構(gòu)建入門
Jetty 插件
從 Gradle 中調(diào)用 Ant
標(biāo)準(zhǔn)的 Gradle 插件
Web 工程構(gòu)建
JDepend 插件
編寫構(gòu)建腳本

任務(wù)詳述

在入門教程構(gòu)建基礎(chǔ)中,你已經(jīng)學(xué)習(xí)了如何創(chuàng)建簡單的任務(wù)。之后您還學(xué)習(xí)了如何將其他行為添加到這些任務(wù)中。并且你已經(jīng)學(xué)會(huì)了如何創(chuàng)建任務(wù)之間的依賴。這都是簡單的任務(wù)。但 Gradle 讓任務(wù)的概念更深遠(yuǎn)。Gradle 支持增強(qiáng)的任務(wù),也就是,有自己的屬性和方法的任務(wù)。這是真正的與你所使用的 Ant 目標(biāo)(target)的不同之處。這種增強(qiáng)的任務(wù)可以由你提供,或由 Gradle 提供。

定義任務(wù)

在構(gòu)建基礎(chǔ)中我們已經(jīng)看到如何通過關(guān)鍵字這種風(fēng)格來定義任務(wù)。在某些情況中,你可能需要使用這種關(guān)鍵字風(fēng)格的幾種不同的變式。例如,在表達(dá)式中不能用這種關(guān)鍵字風(fēng)格。

定義任務(wù)

build.gradle

task(hello) << {
    println "hello"
}
task(copy, type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}  

您還可以使用字符串作為任務(wù)名稱:

定義任務(wù) — — 使用字符串作為任務(wù)名稱

build.gradle

task('hello') <<
{
    println "hello"
}
task('copy', type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}  

對(duì)于定義任務(wù),有一種替代的語法你可能更愿意使用:

使用替代語法定義任務(wù)

build.gradle

tasks.create(name: 'hello') << {
    println "hello"
}
tasks.create(name: 'copy', type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}  

在這里我們將任務(wù)添加到 tasks 集合。關(guān)于 create() 方法的更多變化可以看看 TaskContainer。

定位任務(wù)

你經(jīng)常需要在構(gòu)建文件中查找你所定義的任務(wù),例如,為了去配置或是依賴它們。對(duì)這樣的情況,有很多種方法。首先,每個(gè)任務(wù)都可作為項(xiàng)目的一個(gè)屬性,并且使用任務(wù)名稱作為這個(gè)屬性名稱:

以屬性方式訪問任務(wù)

build.gradle

task hello
println hello.name
println project.hello.name  

任務(wù)也可以通過 tasks 集合來訪問。

通過 tasks 集合訪問任務(wù)

build.gradle

task hello
println tasks.hello.name
println tasks['hello'].name  

您可以從任何項(xiàng)目中,使用 tasks.getByPath() 方法獲取任務(wù)路徑并且通過這個(gè)路徑來訪問任務(wù)。你可以用任務(wù)名稱,相對(duì)路徑或者是絕對(duì)路徑作為參數(shù)調(diào)用 getByPath() 方法。

通過路徑訪問任務(wù)

build.gradle

project(':projectA') {
    task hello
}
task hello
println tasks.getByPath('hello').path
println tasks.getByPath(':hello').path
println tasks.getByPath('projectA:hello').path
println tasks.getByPath(':projectA:hello').path  

gradle -q hello的輸出結(jié)果

> gradle -q hello
:hello
:hello
:projectA:hello
:projectA:hello  

有關(guān)查找任務(wù)的更多選項(xiàng),可以看一下 TaskContainer。

配置任務(wù)

作為一個(gè)例子,讓我們看看由 Gradle 提供的 Copy 任務(wù)。若要?jiǎng)?chuàng)建 Copy 任務(wù),您可以在構(gòu)建腳本中聲明:

創(chuàng)建一個(gè)復(fù)制任務(wù)

build.gradle

task myCopy(type: Copy)  

上面的代碼創(chuàng)建了一個(gè)什么都沒做的復(fù)制任務(wù)??梢允褂盟?API 來配置這個(gè)任務(wù)(見 Copy)。下面的示例演示了幾種不同的方式來實(shí)現(xiàn)相同的配置。

配置任務(wù)的幾種方式

build.gradle

Copy myCopy = task(myCopy, type: Copy)
myCopy.from 'resources'
myCopy.into 'target'
myCopy.include('**/*.txt', '**/*.xml', '**/*.properties')  

這類似于我們通常在 Java 中配置對(duì)象的方式。您必須在每一次的配置語句重復(fù)上下文 (myCopy)。這顯得很冗余并且很不好讀。

還有另一種配置任務(wù)的方式。它也保留了上下文,且可以說是可讀性最強(qiáng)的。它是我們通常最喜歡的方式。

配置任務(wù)-使用閉包

build.gradle

task myCopy(type: Copy)
myCopy {
   from 'resources'
   into 'target'
   include('**/*.txt', '**/*.xml', '**/*.properties')
}  

這種方式適用于任何任務(wù)。該例子的第 3 行只是 tasks.getByName() 方法的簡潔寫法。特別要注意的是,如果您向 getByName() 方法傳入一個(gè)閉包,這個(gè)閉包的應(yīng)用是在配置這個(gè)任務(wù)的時(shí)候,而不是任務(wù)執(zhí)行的時(shí)候。

您也可以在定義一個(gè)任務(wù)的時(shí)候使用一個(gè)配置閉包。

使用閉包定義任務(wù)

build.gradle

task copy(type: Copy) {
   from 'resources'
   into 'target'
   include('**/*.txt', '**/*.xml', '**/*.properties')
}  

對(duì)任務(wù)添加依賴

定義任務(wù)的依賴關(guān)系有幾種方法。在任務(wù)依賴中,已經(jīng)向你介紹了使用任務(wù)名稱來定義依賴。任務(wù)的名稱可以指向同一個(gè)項(xiàng)目中的任務(wù),或者其他項(xiàng)目中的任務(wù)。要引用另一個(gè)項(xiàng)目中的任務(wù),你需要把它所屬的項(xiàng)目的路徑作為前綴加到它的名字中。下面是一個(gè)示例,添加了從 projectA:taskX 到 projectB:taskY 的依賴關(guān)系:

從另一個(gè)項(xiàng)目的任務(wù)上添加依賴

build.gradle

project('projectA') {
    task taskX(dependsOn: ':projectB:taskY') << {
        println 'taskX'
    }
}
project('projectB') {
    task taskY << {
        println 'taskY'
    }
}  

gradle -q taskX 的輸出結(jié)果

> gradle -q taskX
taskY
taskX  

您可以使用一個(gè) Task 對(duì)象而不是任務(wù)名稱來定義依賴,如下:

使用 task 對(duì)象添加依賴

build.gradle

task taskX << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}
taskX.dependsOn taskY  

gradle -q taskX的輸出結(jié)果

> gradle -q taskX
taskY
taskX  

對(duì)于更高級(jí)的用法,您可以使用閉包來定義任務(wù)依賴。在計(jì)算依賴時(shí),閉包會(huì)被傳入正在計(jì)算依賴的任務(wù)。這個(gè)閉包應(yīng)該返回一個(gè) Task 對(duì)象或是 Task 對(duì)象的集合,返回值會(huì)被作為這個(gè)任務(wù)的依賴項(xiàng)。下面的示例是從 taskX 加入了項(xiàng)目中所有名稱以 lib 開頭的任務(wù)的依賴:

使用閉包添加依賴

build.gradle

task taskX << {
    println 'taskX'
}
taskX.dependsOn {
    tasks.findAll { task -> task.name.startsWith('lib') }
}
task lib1 << {
    println 'lib1'
}
task lib2 << {
    println 'lib2'
}
task notALib << {
    println 'notALib'
}  

gradle -q taskX 的輸出結(jié)果

> gradle -q taskX
lib1
lib2
taskX  

有關(guān)任務(wù)依賴的詳細(xì)信息,請(qǐng)參閱 Task 的 API。

任務(wù)排序

任務(wù)排序還是一個(gè)孵化中的功能。請(qǐng)注意此功能在以后的 Gradle 版本中可能會(huì)改變。

在某些情況下,控制兩個(gè)任務(wù)的執(zhí)行的順序,而不引入這些任務(wù)之間的顯式依賴,是很有用的。任務(wù)排序和任務(wù)依賴之間的主要區(qū)別是,排序規(guī)則不會(huì)影響那些任務(wù)的執(zhí)行,而僅將執(zhí)行的順序。

任務(wù)排序在許多情況下可能很有用:

  • 強(qiáng)制任務(wù)順序執(zhí)行: 如,'build' 永遠(yuǎn)不會(huì)在 'clean' 前面執(zhí)行。
  • 在構(gòu)建中盡早進(jìn)行構(gòu)建驗(yàn)證:如,驗(yàn)證在開始發(fā)布的工作前有一個(gè)正確的證書。
  • 通過在長久驗(yàn)證前運(yùn)行快速驗(yàn)證以得到更快的反饋:如,單元測試應(yīng)在集成測試之前運(yùn)行。
  • 一個(gè)任務(wù)聚合了某一特定類型的所有任務(wù)的結(jié)果:如,測試報(bào)告任務(wù)結(jié)合了所有執(zhí)行的測試任務(wù)的輸出。

有兩種排序規(guī)則是可用的:"必須在之后運(yùn)行"和"應(yīng)該在之后運(yùn)行"。

通過使用 “ 必須在之后運(yùn)行”的排序規(guī)則,您可以指定 taskB 必須總是運(yùn)行在 taskA 之后,無論 taskA 和 taskB 這兩個(gè)任務(wù)在什么時(shí)候被調(diào)度執(zhí)行。這被表示為 taskB.mustRunAfter(taskA) 。“應(yīng)該在之后運(yùn)行”的排序規(guī)則與其類似,但沒有那么嚴(yán)格,因?yàn)樗趦煞N情況下會(huì)被忽略。首先是如果使用這一規(guī)則引入了一個(gè)排序循環(huán)。其次,當(dāng)使用并行執(zhí)行,并且一個(gè)任務(wù)的所有依賴項(xiàng)除了任務(wù)應(yīng)該在之后運(yùn)行之外所有條件已滿足,那么這個(gè)任務(wù)將會(huì)運(yùn)行,不管它的“應(yīng)該在之后運(yùn)行”的依賴項(xiàng)是否已經(jīng)運(yùn)行了。當(dāng)傾向于更快的反饋時(shí),會(huì)使用“應(yīng)該在之后運(yùn)行”的規(guī)則,因?yàn)檫@種排序很有幫助但要求不嚴(yán)格。

目前使用這些規(guī)則仍有可能出現(xiàn) taskA 執(zhí)行而 taskB 沒有執(zhí)行,或者 taskB 執(zhí)行而 taskA 沒有執(zhí)行。

添加 '必須在之后運(yùn)行 ' 的任務(wù)排序

build.gradle

task taskX << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}
taskY.mustRunAfter taskX  

gradle -q taskY taskX 的輸出結(jié)果

> gradle -q taskY taskX
taskX
taskY  

添加 '應(yīng)該在之后運(yùn)行 ' 的任務(wù)排序

build.gradle

task taskX << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}
taskY.shouldRunAfter taskX  

gradle -q taskY taskX 的輸出結(jié)果

> gradle -q taskY taskX
taskX
taskY  

在上面的例子中,它仍有可能執(zhí)行 taskY 而不會(huì)導(dǎo)致 taskX 也運(yùn)行:

任務(wù)排序并不意味著任務(wù)執(zhí)行

gradle -q taskY 的輸出結(jié)果

> gradle -q taskY
taskY  

如果想指定兩個(gè)任務(wù)之間的“必須在之后運(yùn)行”和“應(yīng)該在之后運(yùn)行”排序,可以使用 Task.mustRunAfter() 和 Task.shouldRunAfter() 方法。這些方法接受一個(gè)任務(wù)實(shí)例、 任務(wù)名稱或 Task.dependsOn()所接受的任何其他輸入作為參數(shù)。

請(qǐng)注意"B.mustRunAfter(A)"或"B.shouldRunAfter(A)"并不意味著這些任務(wù)之間的任何執(zhí)行上的依賴關(guān)系:

  • 它是可以獨(dú)立地執(zhí)行任務(wù) A 和 B 的。排序規(guī)則僅在這兩項(xiàng)任務(wù)計(jì)劃執(zhí)行時(shí)起作用。
  • 當(dāng)--continue 參數(shù)運(yùn)行時(shí),可能會(huì)是 A 執(zhí)行失敗后B執(zhí)行了。

如之前所述,如果“應(yīng)該在之后運(yùn)行”的排序規(guī)則引入了排序循環(huán),那么它將會(huì)被忽略。

當(dāng)引入循環(huán)時(shí),“應(yīng)該在其之后運(yùn)行”的任務(wù)排序會(huì)被忽略

build.gradle

task taskX << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}
task taskZ << {
    println 'taskZ'
}
taskX.dependsOn taskY
taskY.dependsOn taskZ
taskZ.shouldRunAfter taskX  

gradle -q taskX 的輸出結(jié)果

> gradle -q taskX
taskZ
taskY
taskX  

向任務(wù)添加描述

你可以向你的任務(wù)添加描述。例如,當(dāng)執(zhí)行 gradle tasks 時(shí)顯示這個(gè)描述。

向任務(wù)添加描述

build.gradle

task copy(type: Copy) {
   description 'Copies the resource directory to the target directory.'
   from 'resources'
   into 'target'
   include('**/*.txt', '**/*.xml', '**/*.properties')
}  

替換任務(wù)

有時(shí)您想要替換一個(gè)任務(wù)。例如,您想要把通過 Java 插件添加的一個(gè)任務(wù)與不同類型的一個(gè)自定義任務(wù)進(jìn)行交換。你可以這樣實(shí)現(xiàn):

重寫任務(wù)

build.gradle

task copy(type: Copy)
task copy(overwrite: true) << {
    println('I am the new one.')
}  

gradle -q copy 的輸出結(jié)果

> gradle -q copy
I am the new one.  

在這里我們用一個(gè)簡單的任務(wù)替換 Copy 類型的任務(wù)。當(dāng)創(chuàng)建這個(gè)簡單的任務(wù)時(shí),您必須將 overwrite 屬性設(shè)置為 true。否則 Gradle 將拋出異常,說這種名稱的任務(wù)已經(jīng)存在。

跳過任務(wù)

Gradle 提供多種方式來跳過任務(wù)的執(zhí)行。

使用斷言

你可以使用 onlyIf()方法將斷言附加到一項(xiàng)任務(wù)中。如果斷言結(jié)果為 true,才會(huì)執(zhí)行任務(wù)的操作。你可以用一個(gè)閉包來實(shí)現(xiàn)斷言。閉包會(huì)作為一個(gè)參數(shù)傳給任務(wù),并且任務(wù)應(yīng)該執(zhí)行時(shí)返回 true,或任務(wù)應(yīng)該跳過時(shí)返回 false。斷言只在任務(wù)要執(zhí)行前才計(jì)算。

使用斷言跳過一個(gè)任務(wù)

build.gradle

task hello << {
    println 'hello world'
}
hello.onlyIf { !project.hasProperty('skipHello') }  

gradle hello -PskipHello 的輸出結(jié)果

> gradle hello -PskipHello
:hello SKIPPED
BUILD SUCCESSFUL
Total time: 1 secs  

使用 StopExecutionException

如果跳過任務(wù)的規(guī)則不能與斷言同時(shí)表達(dá),您可以使用 StopExecutionException。如果一個(gè)操作(action)拋出了此異常,那么這個(gè)操作(action)接下來的行為和這個(gè)任務(wù)的其他 操作(action)都會(huì)被跳過。構(gòu)建會(huì)繼續(xù)執(zhí)行下一個(gè)任務(wù)。

使用 StopExecutionException 跳過任務(wù)

build.gradle

task compile << {
    println 'We are doing the compile.'
}
compile.doFirst {
    // Here you would put arbitrary conditions in real life. But we use this as an integration test, so we want defined behavior.
    if (true) { throw new StopExecutionException() }
}
task myTask(dependsOn: 'compile') << {
   println 'I am not affected'
}  

gradle -q myTask 的輸出結(jié)果

> gradle -q myTask
I am not affected  

如果您使用由 Gradle 提供的任務(wù),那么此功能將非常有用。它允許您向一個(gè)任務(wù)的內(nèi)置操作中添加執(zhí)行條件。

啟用和禁用任務(wù)

每一項(xiàng)任務(wù)有一個(gè)默認(rèn)值為 true 的 enabled 標(biāo)記。將它設(shè)置為 false,可以不讓這個(gè)任務(wù)的任何操作執(zhí)行。

啟用和禁用任務(wù)

build.gradle

task disableMe << {
    println 'This should not be printed if the task is disabled.'
}
disableMe.enabled = false  

Gradle disableMe 的輸出結(jié)果

> gradle disableMe
:disableMe SKIPPED
BUILD SUCCESSFUL
Total time: 1 secs  

跳過處于最新狀態(tài)的任務(wù)

如果您使用 Gradle 自帶的任務(wù),如 Java 插件所添加的任務(wù)的話,你可能已經(jīng)注意到 Gradle 將跳過處于最新狀態(tài)的任務(wù)。這種行在您自己定義的任務(wù)上也有效,而不僅僅是內(nèi)置任務(wù)。

聲明一個(gè)任務(wù)的輸入和輸出

讓我們來看一個(gè)例子。在這里我們的任務(wù)從一個(gè) XML 源文件生成多個(gè)輸出文件。讓我們運(yùn)行它幾次。

一個(gè)生成任務(wù)

build.gradle

task transform {
    ext.srcFile = file('mountains.xml')
    ext.destDir = new File(buildDir, 'generated')
    doLast {
        println "Transforming source file."
        destDir.mkdirs()
        def mountains = new XmlParser().parse(srcFile)
        mountains.mountain.each { mountain ->
            def name = mountain.name[0].text()
            def height = mountain.height[0].text()
            def destFile = new File(destDir, "${name}.txt")
            destFile.text = "$name -> ${height}\n"
        }
    }
}  

gradle transform 的輸出結(jié)果

> gradle transform
:transform
Transforming source file.  

gradle transform的輸出結(jié)果

> gradle transform
:transform
Transforming source file.  

請(qǐng)注意 Gradle 第二次執(zhí)行執(zhí)行這項(xiàng)任務(wù)時(shí),即使什么都未作改變,也沒有跳過該任務(wù)。我們的示例任務(wù)被用一個(gè)操作(action)閉包來定義。Gradle 不知道這個(gè)閉包做了什么,也無法自動(dòng)判斷這個(gè)任務(wù)是否為最新狀態(tài)。若要使用 Gradle 的最新狀態(tài)(up-to-date)檢查,您需要聲明這個(gè)任務(wù)的輸入和輸出。

每個(gè)任務(wù)都有一個(gè) inputs 和 outputs 的屬性,用來聲明任務(wù)的輸入和輸出。下面,我們修改了我們的示例,聲明它將 XML 源文件作為輸入,并產(chǎn)生輸出到一個(gè)目標(biāo)目錄。讓我們運(yùn)行它幾次。

聲明一個(gè)任務(wù)的輸入和輸出

build.gradle

task transform {
    ext.srcFile = file('mountains.xml')
    ext.destDir = new File(buildDir, 'generated')
    inputs.file srcFile
    outputs.dir destDir
    doLast {
        println "Transforming source file."
        destDir.mkdirs()
        def mountains = new XmlParser().parse(srcFile)
        mountains.mountain.each { mountain ->
            def name = mountain.name[0].text()
            def height = mountain.height[0].text()
            def destFile = new File(destDir, "${name}.txt")
            destFile.text = "$name -> ${height}\n"
        }
    }
}  

gradle transform 的輸出結(jié)果

> gradle transform
:transform
Transforming source file.  

gradle transform 的輸出結(jié)果

> gradle transform
:transform UP-TO-DATE  

現(xiàn)在,Gradle 知道哪些文件要檢查以確定任務(wù)是否為最新狀態(tài)。

任務(wù)的 inputs 屬性是 TaskInputs 類型。任務(wù)的 outputs 屬性是 TaskOutputs 類型。

一個(gè)沒有定義輸出的任務(wù)將永遠(yuǎn)不會(huì)被當(dāng)作是最新的。對(duì)于任務(wù)的輸出并不是文件的場景,或者是更復(fù)雜的場景, TaskOutputs.upToDateWhen() 方法允許您以編程方式計(jì)算任務(wù)的輸出是否應(yīng)該被判斷為最新狀態(tài)。

一個(gè)只定義了輸出的任務(wù),如果自上一次構(gòu)建以來它的輸出沒有改變,那么它會(huì)被判定為最新狀態(tài)。

它是怎么實(shí)現(xiàn)的?

在第一次執(zhí)行任務(wù)之前,Gradle 對(duì)輸入進(jìn)行一次快照。這個(gè)快照包含了輸入文件集和每個(gè)文件的內(nèi)容的哈希值。然后 Gradle 執(zhí)行該任務(wù)。如果任務(wù)成功完成,Gradle 將對(duì)輸出進(jìn)行一次快照。該快照包含輸出文件集和每個(gè)文件的內(nèi)容的哈希值。Gradle 會(huì)保存這兩個(gè)快照,直到任務(wù)的下一次執(zhí)行。

之后每一次,在執(zhí)行任務(wù)之前,Gradle 會(huì)對(duì)輸入和輸出進(jìn)行一次新的快照。如果新的快照和前一次的快照一樣,Gradle 會(huì)假定這些輸出是最新狀態(tài)的并跳過該任務(wù)。如果它們不一則, Gradle 則會(huì)執(zhí)行該任務(wù)。Gradle 會(huì)保存這兩個(gè)快照,直到任務(wù)的下一次執(zhí)行。

請(qǐng)注意,如果一個(gè)任務(wù)有一個(gè)指定的輸出目錄,在它上一次執(zhí)行之后添加到該目錄的所有文件都將被忽略,并且不會(huì)使這個(gè)任務(wù)成為過時(shí)狀態(tài)。這是不相關(guān)的任務(wù)可以在不互相干擾的情況下共用一個(gè)輸出目錄。如果你因?yàn)橐恍├碛啥幌脒@樣,請(qǐng)考慮使用 TaskOutputs.upToDateWhen()

任務(wù)規(guī)則

有時(shí)你想要有這樣一項(xiàng)任務(wù),它的行為依賴于參數(shù)數(shù)值范圍的一個(gè)大數(shù)或是無限的數(shù)字。任務(wù)規(guī)則是提供此類任務(wù)的一個(gè)很好的表達(dá)方式:

任務(wù)規(guī)則

build.gradle

tasks.addRule("Pattern: ping<ID>") { String taskName ->
    if (taskName.startsWith("ping")) {
        task(taskName) << {
            println "Pinging: " + (taskName - 'ping')
        }
    }
}  

Gradle q pingServer1 的輸出結(jié)果

> gradle -q pingServer1
Pinging: Server1  

這個(gè)字符串參數(shù)被用作這條規(guī)則的描述。當(dāng)對(duì)這個(gè)例子運(yùn)行 gradle tasks 的時(shí)候,這個(gè)描述會(huì)被顯示。

規(guī)則不只是從命令行調(diào)用任務(wù)才起作用。你也可以對(duì)基于規(guī)則的任務(wù)創(chuàng)建依賴關(guān)系:

基于規(guī)則的任務(wù)依賴

build.gradle

tasks.addRule("Pattern: ping<ID>") { String taskName ->
    if (taskName.startsWith("ping")) {
        task(taskName) << {
            println "Pinging: " + (taskName - 'ping')
        }
    }
}
task groupPing {
    dependsOn pingServer1, pingServer2
}  

Gradle q groupPing 的輸出結(jié)果

> gradle -q groupPing
Pinging: Server1
Pinging: Server2  

析構(gòu)器任務(wù)

析構(gòu)器任務(wù)是一個(gè)孵化中的功能 。當(dāng)最終的任務(wù)準(zhǔn)備運(yùn)行時(shí),析構(gòu)器任務(wù)會(huì)自動(dòng)地添加到任務(wù)圖中。

添加一個(gè)析構(gòu)器任務(wù)

build.gradle

task taskX << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}
taskX.finalizedBy taskY  

gradle -q taskX 的輸出結(jié)果

> gradle -q taskX
taskX
taskY  

即使最終的任務(wù)執(zhí)行失敗,析構(gòu)器任務(wù)也會(huì)被執(zhí)行。

執(zhí)行失敗的任務(wù)的任務(wù)析構(gòu)器

build.gradle

task taskX << {
    println 'taskX'
    throw new RuntimeException()
}
task taskY << {
    println 'taskY'
}
taskX.finalizedBy taskY  

gradle -q taskX 的輸出結(jié)果

> gradle -q taskX
taskX
taskY  

另一方面,如果最終的任務(wù)什么都不做的話,比如由于失敗的任務(wù)依賴項(xiàng)或如果它被認(rèn)為是最新的狀態(tài),析構(gòu)任務(wù)不會(huì)執(zhí)行。

在不管構(gòu)建成功或是失敗,都必須清理創(chuàng)建的資源的情況下,析構(gòu)認(rèn)為是很有用的。這樣的資源的一個(gè)例子是,一個(gè) web 容器會(huì)在集成測試任務(wù)前開始,并且在之后關(guān)閉,即使有些測試失敗。

你可以使用 Task.finalizedBy()方法指定一個(gè)析構(gòu)器任務(wù)。這個(gè)方法接受一個(gè)任務(wù)實(shí)例、任務(wù)名稱或<a4><c5>Task.dependsOn()</c5></a4>所接受的任何其他輸入作為參數(shù)。

總結(jié)

如果你是從 Ant 轉(zhuǎn)過來的,像 Copy 這種增強(qiáng)的 Gradle 任務(wù),看起來就像是一個(gè) Ant 目標(biāo)(target)和一個(gè) Ant 任務(wù)(task)之間的混合物。實(shí)際上確實(shí)是這樣子。Gradle 沒有像 Ant 那樣對(duì)任務(wù)和目標(biāo)進(jìn)行分離。簡單的 Gradle 任務(wù)就像 Ant 的目標(biāo),而增強(qiáng)的 Gradle 任務(wù)還包括 Ant 任務(wù)方面的內(nèi)容。Gradle 的所有任務(wù)共享一個(gè)公共 API,您可以創(chuàng)建它們之間的依賴性。這樣的一個(gè)任務(wù)可能會(huì)比一個(gè) Ant 任務(wù)更好配置。它充分利用了類型系統(tǒng),更具有表現(xiàn)力而且易于維護(hù)。

上一篇:Groovy 插件下一篇:Gradle 插件