我无法理解gradle中的groovy语法。
如果命名参数(在groovy中)使用:
后缀,那么我假设代码apply plugin: 'java'
意味着调用函数apply(plugin = 'java')
。这很奇怪,因为函数apply
甚至没有定义。以下是我的gradle脚本中的错误:
println apply.getClass()
> Could not get unknown property 'apply' for root project 'Simple' of type
org.gradle.api.Project.
那么apply
是什么以及定义在哪里?为什么上面的代码不打印apply
元素的类?
另外一件我觉得奇怪的事情是:
dependencies {
compile 'org.slf4j:slf4j-api:1.7.12'
testCompile 'junit:junit:4.12'
}
语法表明{}
中包含的代码是一个闭包,但compile
和testCompile
元素是什么?如果它是一个闭包,那么上面的代码只会将'junit:junit:4.12'
作为字符串返回,其余代码将无法编译。它看起来更像是地图的定义。但同样,如果上面的代码是数据,那么我应该能够在groovysh
shell中输入它。
groovy:000> dependencies {
compile 'org.slf4j:slf4j-api:1.7.12'
testCompile 'junit:junit:4.12'
}
groovy:001> groovy:002> groovy:003> ERROR groovy.lang.MissingMethodException:
No signature of method: groovysh_evaluate.dependencies() is applicable for argument types: (groovysh_evaluate$_run_closure1) values: [groovysh_evaluate$_run_closure1@b7c4869]
这让我感到困惑。我认为gradle脚本只是groovy脚本,但似乎gradle DSL为groovy语言添加了元素。一个groovy clojure成为一个map,一个带有命名参数的函数调用变得不同。
有人可以在这个groovy DSL上启发我;)
答案 0 :(得分:3)
plugin: 'java'
是一张时髦的地图。请参阅Project.apply() documentation中的groovy documentation及此语法的说明。
关于依赖关系,请参阅DependencyHandler。
Groovy是一种非常动态的语言,您可以在其中实际调用非声明的方法,并让处理程序根据调用的方法名称执行某些操作。 AFAIK,这就是这里使用的技巧。请参阅source code。
我不是一个时髦的开发人员,虽然我发现DSL优雅,但我也觉得它有时令人困惑,因为我发现很难将DSL的某些部分与文档中的具体方法联系起来。但你最终会理解它并习惯它。
答案 1 :(得分:2)
compile 'org.slf4j:slf4j-api:1.7.12'
不是地图,而是方法调用。在Groovy中,您可以省略括号,因此调用等同于
compile( 'org.slf4j:slf4j-api:1.7.12' )
Gradle中的这些方法也可以采用第二个参数:
compile( 'org.slf4j:slf4j-api:1.7.12' ){ exclude module:'log4j' }
在这种情况下,module:'log4j'
是带有省略方括号的地图,可以将调用重写为
compile( 'org.slf4j:slf4j-api:1.7.12' ){ exclude( [module:'log4j'] ) }