理想情况下,Groovy 构建脚本看起来大多像配置:设置项目的一些属性、配置依赖项、声明任务等等。该配置基于 Groovy 语言构造。本入门书旨在解释这些构造是什么,以及最重要的是它们与 Gradle 的 API 文档的关系。
物体Project
由于 Groovy 是一种基于 Java 的面向对象语言,因此它的属性和方法适用于对象。在某些情况下,对象是隐式的——特别是在构建脚本的顶层,即不嵌套在块内{}
。
考虑构建脚本的这个片段,其中包含不合格的属性和块:
version = '1.0.0.GA'
configurations {
...
}
和version
都是org.gradle.api.Projectconfigurations {}
的一部分。
此示例反映了每个 Groovy 构建脚本如何由Project
.如果您看到不合格的元素并且不知道它是在哪里定义的,请务必检查Project
API 文档以查看它是否来自该元素。
避免在构建脚本中使用Groovy MetaClass编程技术。 Gradle 提供了自己的 API 用于添加动态运行时属性。 使用 Groovy 特定的元编程可能会导致构建在构建之间保留大量内存,最终导致 Gradle 守护程序运行内存不足。 |
特性
<obj>.<name> // Get a property value
<obj>.<name> = <value> // Set a property to a new value
"$<name>" // Embed a property value in a string
"${<obj>.<name>}" // Same as previous (embedded value)
version = '1.0.1'
myCopyTask.description = 'Copies some files'
file("$projectDir/src")
println "Destination: ${myCopyTask.destinationDir}"
属性代表对象的某种状态。标志的存在=
清楚地表明您正在查看一处房产。否则,一个限定名称(以开头<obj>.
)没有任何其他修饰也是一种属性。
如果名称不合格,则可能是以下之一:
请注意,插件可以将自己的属性添加到对象中Project
。 API文档列出了核心插件添加的所有属性。如果您很难找到属性的来源,请检查构建使用的插件的文档。
当在构建脚本中引用由非核心插件添加的项目属性时,请考虑为其添加前缀project. - 很明显该属性属于项目对象。
|
API 文档中的属性
Groovy DSL 参考显示了构建脚本中使用的属性,但 Javadoc 仅显示方法。这是因为属性是作为幕后方法实现的:
-
如果有一个以零参数命名的方法返回与该属性相同的类型,则可以读取该属性。
get<PropertyName>
-
如果存在一个以一个参数命名的方法,该方法与该属性具有相同类型且返回类型为,则可以修改该属性。
set<PropertyName>
void
请注意,属性名称通常以小写字母开头,但该字母在方法名称中为大写字母。所以getter方法getProjectVersion()
对应的是property projectVersion
。当名称以至少两个大写字母开头时,此约定不适用,在这种情况下,大小写不会发生变化。例如,getRAM()
对应于属性RAM
.
project.getVersion()
project.version
project.setVersion('1.0.1')
project.version = '1.0.1'
方法
<obj>.<name>() // Method call with no arguments
<obj>.<name>(<arg>, <arg>) // Method call with multiple arguments
<obj>.<name> <arg>, <arg> // Method call with multiple args (no parentheses)
myCopyTask.include '**/*.xml', '**/*.properties'
ext.resourceSpec = copySpec() // `copySpec()` comes from `Project`
file('src/main/java')
println 'Hello, World!'
方法代表对象的某些行为,尽管 Gradle 也经常使用方法来配置对象的状态。方法可以通过其参数或空括号来识别。请注意,有时需要括号,例如当方法具有零参数时,因此您可能会发现始终使用括号最简单。
Gradle 有一个约定,如果一个方法与基于集合的属性具有相同的名称,则该方法会将其值附加到该集合。 |
积木
块也是方法,只是最后一个参数具有特定类型。
<obj>.<name> {
...
}
<obj>.<name>(<arg>, <arg>) {
...
}
plugins {
id 'java-library'
}
configurations {
assets
}
sourceSets {
main {
java {
srcDirs = ['src']
}
}
}
dependencies {
implementation project(':util')
}
块是一种一次性配置构建元素多个方面的机制。它们还提供了一种嵌套配置的方法,从而产生结构化数据的形式。
您应该了解块的两个重要方面:
-
它们被实现为具有特定签名的方法。
-
他们可以更改不合格方法和属性的目标(“委托”)。
两者都基于 Groovy 语言功能,我们将在以下部分中对其进行解释。
块方法签名
您可以通过其签名(或更具体地说,其参数类型)轻松地将方法识别为块背后的实现。如果一个方法对应一个块:
-
它必须至少有一个参数。
-
最后一个参数必须是org.gradle.api.Action
groovy.lang.Closure
类型。
例如,Project.copy(Action)满足这些要求,因此您可以使用以下语法:
copy {
into layout.buildDirectory.dir("tmp")
from 'custom-resources'
}
into()
这就引出了如何工作的问题from()
。它们显然是方法,但是您可以在 API 文档中的哪里找到它们?答案来自于对对象委托的理解。
代表团
属性部分列出了可能发现不合格属性的位置。一个常见的地方是Project
物体上。但是块内的那些不合格的属性和方法还有一个替代来源:块的委托对象。
为了帮助解释这个概念,请考虑上一节中的最后一个示例:
copy {
into layout.buildDirectory.dir("tmp")
from 'custom-resources'
}
此示例中的所有方法和属性都是不合格的。你可以很容易地在API 文档copy()
中找到and ,但是and呢?这些是针对该块的代表来解决的。该代表的类型是什么?您需要检查该 API 文档。layout
Project
into()
from()
copy {}
有两种方法可以确定委托类型,具体取决于块方法的签名:
-
对于
Action
参数,请查看类型的参数。在上面的示例中,方法签名是
copy(Action<? super CopySpec>)
,尖括号内的位告诉您委托类型 - 在本例中为CopySpec 。 -
对于
Closure
参数,文档将在描述中明确说明正在配置的类型或委托的类型(同一事物的不同术语)。
所有新的 Gradle API 都声明Action
参数类型而不是Closure
,这使得选择委托类型变得非常容易。即使是较旧的 API,Action
除了旧 API 之外还有一种变体Closure
。