ext {
springVersion = "3.1.0.RELEASE"
emailNotification = "[email protected]"
}
上面的代码是build.gradle的片段
我理解使用 { } 闭包参数调用 ext 方法。 这是正确的? 所以我认为 gradle 正在访问 springVersion 和 emailNotification。 我将用下面的代码验证我的假设
def ext(data) {
println data.springVersion
}
ext {
springVersion = "3.1.0.RELEASE"
emailNotification = "[email protected]"
}
但运行该代码 出现以下错误。
groovy.lang.MissingPropertyException: No such property: springVersion for class: Test
你具体解释一下ext和code block吗?
ext
是 project.ext
的简写,用于为 project
对象定义 额外属性。 (也可以为许多其他对象定义额外属性。)读取额外属性时,将省略
ext.
(例如 println project.springVersion
或 println springVersion
)。在方法内部也是如此。声明一个名为 ext
的方法是没有意义的。
这里是问题中示例代码产生错误的原因的解释。
代码中:
ext {
springVersion = "3.1.0.RELEASE"
emailNotification = "[email protected]"
}
不将具有 springVersion 和 emailNotification 属性的对象传递给函数“ext”。大括号并不表示 POJO,而是表示闭包。 这就是为什么“ext”函数抱怨它无法访问属性。
传递这样一个闭包(称为配置闭包)的想法是接收函数将:
修改闭包的委托属性以指向闭包属性/方法应作用的对象。
执行闭包()
因此闭包执行,当它引用方法/属性时,这些将在要配置的对象上执行。
因此,对代码进行以下修改将使其正常工作:
class DataObject {
String springVersion;
String emailNotification;
}
def ext(closure) {
def data = new DataObject() // This is the object to configure.
closure.delegate = data;
// need this resolve strategy for properties or they just get
// created in the closure instead of being delegated to the object
// to be configured. For methods you don't need this as the default
// strategy is usually fine.
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure() // execute the configuration closure
println data.springVersion
}
ext {
springVersion = "3.1.0.RELEASE"
emailNotification = "[email protected]"
}
希望这可以帮助。 Groovy 闭包需要一些时间来适应......
通过
ExtraPropertiesExtension
重写 get() 和 set() 是使之前定义的属性的配置语法起作用的关键。
class DataObject {
HashMap<String, Object> props = new HashMap<String, Object>()
Object get(String name) {
return props.get(name)
}
void set(String name, @Nullable Object value) {
props.put(name, value)
}
}
def myExtInstance = new DataObject()
def myExt = { Closure closure ->
def data = myExtInstance
closure.delegate = data;
// need this resolve strategy for properties or they just get
// created in the closure instead of being delegated to the object
// to be configured. For methods you don't need this as the default
// strategy is usually fine.
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure() // execute the configuration closure
println data.springVersion
}
myExt {
springVersion = "3.1.0.RELEASE"
emailNotification = "[email protected]"
}
println "myExtInstance.springVersion" + myExtInstance.springVersion
您必须了解闭包委托策略以及它们在 Groovy 中的工作原理。 默认情况下,您在闭包中访问的任何属性都将查找封闭类或嵌套闭包的情况下的封闭闭包。这两者都被称为 Groovy 中闭包的
owner
。如果您注意到,错误是在抱怨,因为在这种情况下,封闭/拥有的类Test
不包含这些属性。
groovy.lang.MissingPropertyException: No such property: springVersion for class: Test
因此你必须在闭包中设置
delegate
属性来覆盖默认的委托策略。顺便说一句,闭包委托在 Groovy 中是一个“强大的概念”,DSL(领域特定语言)就是围绕它构建的。希望这有帮助。