我很难理解Gradle的Groovy DSL的工作原理。
不幸的是,Gradle是我在日常工作中遇到的Groovy的主要用例,而且我已经注意到,对于许多开发人员来说,他们对Groovy的接触严格是通过Gradle进行的。因此,大多数Gradle用户对Groovy的了解非常有限。
在我对Groovy的有限理解中,以下正则表达式tokenA tokenB { tokenC }
(其中所有标记都不是语言关键字),tokenA
将是我们使用参数tokenB
和最终参数调用的方法是一个关闭。我想想我是正确的,但是我知道我错了,因为在令牌B之后可能需要用逗号才能使该分析正确。
正如您已经知道的那样,我绝不是Groovy开发人员,并且我认为在不学习Groovy基础知识的情况下使用Gradle是一件不好的事,因为它限制了我充分利用其功能。但是,我唯一可行的选择是通过示例学习而不不幸地学习理论。
我确实检查了一些类似的问题,例如this one,但对于我来说足够清晰或完整的答案都没有。
TL; DR
task myTask { doLast {} }
?myTask
而不是task
或后面的类型时,如何将def
解释为标识符?myTask { dependsOn myOtherTask }
,该如何解释?答案 0 :(得分:1)
(免责声明,我不是一个笨拙的开发人员)
运行构建时(例如gradle clean
),将根据build.gradle
对象(由Gradle运行程序创建)评估Project
的内容;请参见API-Gradle Project上的Javadoc;还请阅读整个摘要,因为其中包含很多信息。他们在该页面中阐明:
一个项目有5个方法“作用域”,它会搜索方法:Project对象本身...构建文件...插件通过插件添加到项目中的扩展名... 项目任务 ..为每个任务添加一个方法,使用任务名称作为方法名称...
task myTask { }
应该等效于project.task('myTask')
。它创建一个名为“ myTask”的新任务,并将该任务添加到当前项目中(请参阅Javadoc)。然后,将一个属性添加到项目对象,以便可以将其作为project.myTask
进行访问。 doLast {..}
在该任务对象上调用doLast
方法;请参见Task-doLast
因此,对于您的一些观点:
project.task('myTask').doLast(..)
(也许这里有更多关于闭包的信息)build.gradle
文件“注入”到Project实例中。加上许多其他步骤project.task('myTask')
project.myTask.dependsOn(project.myOtherTask)
(可能带有附加的闭包,或涉及到Action实例)。这是由于任务已作为属性添加到项目中。还要注意,像project.myTask...
这样的显式语句是有效的,可以在build.gradle
脚本中使用;但是冗长,因此很少使用。
答案 1 :(得分:1)
我相信这很古怪,没有什么特别的。这是您需要了解的常规概念。
class MyClass {
void doStuff(String name, Closure c) {
c.call()
}
}
def o = new MyClass()
o.doStuff('x') {
println "hello"
}
class MyClass {
def methodMissing(String name, args) {
println "You invoked ${name}(${args})"
}
}
def o = new MyClass() {
o.thisMethodDoesNotExist('foo')
}
class MyBean {
void include(String pattern) {...}
void exclude(String pattern) {...}
}
class MyClass {
private MyBean myBean = new MyBean()
void doStuff(Closure c) {
c.setDelegate(myBean)
c.call()
}
}
def o = new MyClass()
o.doStuff {
include 'foo'
exclude 'bar'
}
这3个时髦特性在很大程度上解释了gradle脚本中发生的“魔术”行为,使Java开发人员抓狂了。
所以,让我们分解一下片段
task myTask(type:Foo) {
doLast {...}
}
让我们添加一些括号,并添加隐式项目引用。让我们还将闭包提取到变量
中Closure c = {
doLast {...}
}
project.task(project.myTask([type: Foo.class], c))
project.myTask(...)
方法不存在,并且该行为最终通过methodMissing
功能实现。 Gradle会将闭包上的委托设置为任务实例。因此,闭包中的任何方法都将委派给新创建的任务。
最终,这在逻辑上称为
Action<? extends Task> action = { task ->
task.doLast {...}
}
project.tasks.create('myTask', Foo.class, action)