阅读Gradle构建脚本时,我经常遇到以下代码
configurations {
myConfig
}
我知道这段代码用闭包{ myConfig }
调用了函数configurations
,但是这是什么样的闭包体呢?它只是引用了一些未定义的东西,叫做myConfig
。这个闭包在运行的时候是怎么做的呢?毕竟,下面的代码
def myClosure = { foo }
myClosure()
可预测地产生Caught: groovy.lang.MissingPropertyException: No such property: foo for class: Main
。
2条答案
按热度按时间ddhy6vgd1#
Groovy在省略括号时看起来非常奇怪。如果加入闭包委托和元编程,事情可能会与其他语言大不相同。Gradle混合了声明性配置和DSL代码 Package 器中实现的命令式代码,因此“我正在配置这个”与“我正在编写代码来完成这个”之间的界限肯定是模糊的。说到底,它只是运行代码,但这是其中一个时候,从“这一切都只是代码”的Angular 来思考它可以让你去“什么!?”
configurations
块是一个ConfigurationContainer,容器是非常灵活的实体,其中的元素可以是任何你想要的,如果我们像这样重写它,可能会稍微不那么奇怪:当有人写
myConfig
时不带括号,就相当于一个空的闭包块,这意味着实际上接受了默认值,现在,我用更熟悉更具体的例子替换了myConfig(开发、分段、但您可以想象,我们可能希望使配置更加灵活,客户可以在此定义任何适合其环境的内容。还请注意,我在后面添加了空的闭包块,以显示这些Configurations可以进一步配置如下属性:那么所有这些是如何在幕后实现的呢?一旦你理解了
delegate
属性在groovy闭包中的作用,事情就变得非常简单了。如果你自己实现ConfigurationContainer
,你可以这样做(这是一个松散的伪代码):现在,如果您查看Groovy代码(如果您想创建类似的内容,请参阅NamedDomainObjectContainer),这并不是完全正确的做法,但您可以这样想。
1.我使用元编程方法
methodMissing
来捕获用户声明的任何配置名称(例如dev、staging、production、aws、azure等)。1.创建一个
Config
对象,该对象可能包含此块要配置的一些属性。1.我正在获取第一个参数(期望得到闭包)
1.将
Closure
的delegate
设置为我的Config
对象。1.使用
call()
调用闭包现在,任何对闭包中的属性或方法的调用都将委托给
delegate
属性上的示例集,就像在闭包中写入config.debug
而不需要说config.
一样,闭包**知道 * 你的意思。这意味着,如果我们在Gradle中执行此假设操作,代码可能会变为:
因为我们的
Config
对象已经有一个默认值debug = false
,并且只需要声明生产,而不需要配置。delegate
的概念是您自己尝试调用Closure
时所缺少的。如果不设置delegate
属性,Closure
中的代码就不知道如何找到这些属性并抛出MisingPropertyException
。csbfibhn2#
在Groovy中,您可以将委托分配给闭包,这些对象将用于解析闭包中使用的属性和方法。
例如,将Map分配给闭包
这将打印
bar
。在Groovy Web Console上试试
委托还可以实现methodMissing或propertyMissing以响应动态属性。