【问题标题】:Gradle properties not visible inside extension container closureGradle 属性在扩展容器封闭内不可见
【发布时间】:2018-09-25 08:16:09
【问题描述】:

我正在尝试为 Gradle 编写这个自定义插件,但我无法正确地将参数传递给插件。

在插件中,我正在创建一个扩展,如下所示:

@Override void apply(final Project p) {
    p.extensions.create('myPlugin', MyPluginData.class)

然后在MyPluginData 内部处理def propertyMissing(String name, value) 以接收我期望的客户参数。

最后在客户端应用程序build.gradle 中,我正在尝试配置数据:

println("From root value is " + SOME_VALUE)

myPlugin {
    println("From plugin value is " + SOME_VALUE)
    println("But from plugin 'findProperty' value is " + findProperty("SOME_VALUE"))
    clientDataSet = {
        data_1 = SOME_VALUE
        data_2 = findProperty("SOME_VALUE")
        data_3 = "this is a string"

SOME_VALUE 是在我的项目gradle.properties 上定义的,我在构建过程中得到了以下日志:

来自根的值是来自属性的正确值
来自插件的值为 null
但是从插件的“findProperty”值是属性中的正确值

当然,当接收到data_1 SOME_VALUE 为空时,data_2 具有正确的值,并且数据 3 是我传递的硬​​编码字符串。


我的问题:

我做错了什么或者我的插件上缺少哪个配置,以便客户端应用程序可以直接从其gradle.properties 文件中引用属性?


编辑:根据 cmets 的要求

MyPluginData 只是 extends HashMap<String, MyPluginDataSet>MyPluginDataSet 只是几个字符串。

所以在propertyMissing 内部,我只是将属性名称添加到地图中,并使用字符串创建MyPluginDataSet(稍后用于生成自定义任务)。

缺少的属性函数:

def propertyMissing(String name, value) {
    // Create the new data set and add to the map
    def data = new MyPluginDataSet()
    put(name, data)

    // setup and execute the client closure to configure the data
    def closure = value as Closure
    closure.delegate = data
    closure.resolveStrategy = Closure.DELEGATE_FIRST
    closure.run()
}

【问题讨论】:

  • 您能否提供更多来自您的 MyPluginData 扩展类的代码?特别是您的自定义方法 propertyMissing 实现和 clientDataSet 定义?
  • 嗨 @M.Ricciuti 我刚刚用完整的 propertyMissing 编辑了这个问题。
  • 我尝试重现但没有成功,SOME_VALUE 总是有值
  • 当我让 MyPluginData 继承自 HashMap 时,我重现了这个问题:我想这就是为什么当您尝试从“myPlugin”中访问“SOME_VALUE”时委托/属性解析不起作用的原因闭包:Gradle (Groovy) 将尝试从继承的映射中获取此属性的值,并且不会尝试在其他范围内搜索(请参阅:docs.gradle.org/current/dsl/…
  • 扩展HashMap在我看来不是一个好习惯,myPlugin应该持有一个HashMap实例而不是一个

标签: gradle android-gradle-plugin build.gradle gradle-plugin


【解决方案1】:

通过使MyPluginData 继承自Map<>,我认为您以某种方式“破坏”了属性解析过程(请参阅ExtensionAware)并且 Gradle 不会尝试在不同范围内搜索“SOME_VALUE”属性(所以它不会从 gradle 属性扩展中找到这个属性)

也许您可以尝试通过存储内部映射而不是继承自 Map 来简化 MyPluginData 类?类似的东西:

class MyPluginData {
    Map<String, MyPluginDataSet> internalMap = new HashMap<>()

    def propertyMissing(String name, value) {
        println "Entering propertyMissing for name = $name"
        // Create the new data set and add to the map
        def data = new MyPluginDataSet()
        internalMap.put(name, data)

        // setup and execute the client closure to configure the data
        def closure = value as Closure
        closure.delegate = data
        closure.resolveStrategy = Closure.DELEGATE_FIRST
        closure.run()
    }
}

【讨论】:

  • 太棒了,非常感谢!我是 groovy 的新手,永远不会明白这一点。只需将地图移动到内部属性并进行端到端测试。一切都很完美。
  • 一般来说,优先考虑组合而不是继承是一个好主意。请参阅 Josh Bloch 的《Effective Java》第 16 条! :)
猜你喜欢
  • 2016-03-25
  • 1970-01-01
  • 2012-12-25
  • 2011-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多