You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Groovy编写的Gradle插件在Kotlin DSL中配置PluginExtension的方法

Gradle插件Kotlin DSL配置方案

问题场景

我有一个用Groovy编写的Gradle插件,通过PluginExtension接收配置输入,其Groovy实现代码如下:

class PluginExtension implements GroovyInterceptable {

    private final Project project
    private Map<String, ?> staticTokens
    private Map<String, DynamicToken> dynamicTokens
    private Map<String, Closure> derivedTokens
    private final Closure<Object> propertyGetter

    PluginExtension(Project project) {
        this.project = project
        propertyGetter = findDeploymentProperty.curry(project)
    }

    void setStaticTokens(Map<String, ?> staticTokens) {
        this.staticTokens = staticTokens
    }

    void setDynamicTokens(Map<String, ?> dynamicTokens) {
        this.dynamicTokens = dynamicTokens
                .collectEntries { k, v ->
                    [(k): [refId: { v.refId }, defaultValue: { v.defaultValue }, transform: {
                                v.transform ?: {
                                    it
                                }
                            }]]
                }
                .collectEntries { k, v ->
                    [(k): v as DynamicToken]
                } as Map<String, DynamicToken>
    }
}

在Groovy的build.gradle中,我是这样配置插件的:

deployPreparation {
    staticTokens = [
        appName      : project.name,
        version      : project.version,
        gradleVersion: project.gradle.gradleVersion
    ]
    dynamicTokens = [
        deployName             : [refId: "deploy.name", defaultValue: project.name.toLowerCase().replaceAll("[-]", ""), transform: {
                it.length() > 20 ? it.substring(0, 20) : it
            }],
        jvmAllowedMemory       : [refId: "jvm.allowed.memory", defaultValue: "1024m"],
        jvmActiveProcessors    : [refId: "jvm.active.processors", defaultValue: "2"],

    ]
    derivedTokens = [
        cloudServerGroup: { "${deployName}-${cloudEnvironment}".toString() },
    ]
}

尝试转成Kotlin DSL(build.gradle.kts)时,我写了以下代码:

configure<com.company.search.deploy.prepare.plugin.PluginExtension> {
    staticTokens=mapOf(
            "appName" to project.name,
            "version" to project.version,
            "gradleVersion" to project.gradle.gradleVersion
        ) as Map<String,Any>
}

但遇到报错:

Cannot access 'staticTokens': it is private in 'PluginExtension'

解决方法

1. 调用Setter方法而非直接访问属性

Groovy允许通过staticTokens = xxx的语法自动调用setStaticTokens方法,但Kotlin DSL不会自动做这个映射,需要显式调用Setter方法:

configure<com.company.search.deploy.prepare.plugin.PluginExtension> {
    setStaticTokens(mapOf(
        "appName" to project.name,
        "version" to project.version,
        "gradleVersion" to project.gradle.gradleVersion
    ))
}

2. 完整的Kotlin DSL配置示例

针对dynamicTokens和derivedTokens,需要注意Groovy闭包与Kotlin Lambda的转换,以及DynamicToken的构造适配:

import groovy.lang.Closure

configure<com.company.search.deploy.prepare.plugin.PluginExtension> {
    // 配置staticTokens
    setStaticTokens(mapOf(
        "appName" to project.name,
        "version" to project.version,
        "gradleVersion" to project.gradle.gradleVersion
    ))

    // 配置dynamicTokens
    setDynamicTokens(mapOf(
        "deployName" to mapOf(
            "refId" to "deploy.name",
            "defaultValue" to project.name.lowercase().replace("-", ""),
            "transform" to Closure<Any>(null, null) { it: String ->
                if (it.length > 20) it.substring(0, 20) else it
            }
        ),
        "jvmAllowedMemory" to mapOf(
            "refId" to "jvm.allowed.memory",
            "defaultValue" to "1024m"
        ),
        "jvmActiveProcessors" to mapOf(
            "refId" to "jvm.active.processors",
            "defaultValue" to "2"
        )
    ))

    // 配置derivedTokens(需要将Kotlin Lambda转为Groovy Closure)
    setDerivedTokens(mapOf(
        "cloudServerGroup" to Closure<String>(null, null) {
            "${getProperty("deployName")}-${getProperty("cloudEnvironment")}"
        }
    ))
}

关键说明

  • Kotlin DSL不会像Groovy那样自动将属性赋值映射到Setter方法,必须显式调用setStaticTokens、setDynamicTokens这类方法
  • 对于需要Groovy Closure的地方,要手动将Kotlin Lambda包装为groovy.lang.Closure实例
  • derivedTokens中的闭包需要通过getProperty来访问Extension中的其他属性,因为Kotlin无法直接像Groovy那样隐式访问

内容的提问来源于stack exchange,提问作者codeYogico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 13:18:10