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

基于Java注解生成文件:如何在Gradle任务中运行内联Groovy代码?

在Gradle任务中运行内联Groovy代码的正确方式

问题描述

我需要通过Gradle任务,基于Java类中的注解生成文本文件。一开始参考了JavaExec的示例:

task runScript(type: JavaExec) {
    main = 'com.mrhaki.CurrentDate'
    classpath = sourceSets.main.compileClasspath
}

但这种方式依赖外部类文件,不符合我的需求。于是我尝试在build.gradle里直接定义类:

class MyScript {
    def call() {
        println ":: Vertx version : $io.vertx.core.impl.launcher.commands.VersionCommand.version"
    }
}

task runScript(type: JavaExec) {
    main = 'MyScript'
    classpath = sourceSets.main.runtimeClasspath
}

执行时却报错:

Task :runScript FAILED
Error: Could not find or load main class MyScript

我还试过通过参数传递脚本字符串的方案:

task runGroovyScript(type: JavaExec) {
    classpath = configurations.groovyScript
    main = 'groovy.ui.GroovyMain'
    args '-e', "println 'Hello Gradle!'"
}

但这种方式太不优雅了,请问如何在Gradle任务中运行内联Groovy代码?


解决方案

Gradle本身就是基于Groovy构建的,完全不需要借助JavaExec来运行内联代码,这里有两种更合适的方案:

1. 自定义任务类(适合复杂/可复用逻辑)

继承Gradle的DefaultTask类,用@TaskAction标注执行方法,就能在任务里直接写内联Groovy代码。以你的注解生成文件需求为例:

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

class AnnotationGeneratorTask extends DefaultTask {
    @TaskAction
    void generate() {
        // 定义输出文件路径
        def outputFile = project.file("build/generated/annotations_report.txt")
        // 确保父目录存在
        outputFile.parentFile.mkdirs()

        // 扫描主源码目录下的Java文件,处理注解
        project.sourceSets.main.java.srcDirs.each { srcDir ->
            srcDir.traverse(type: FILES, nameFilter: ~/.*\.java/) { javaFile ->
                def fileContent = javaFile.text
                // 这里替换成你实际要检测的注解,比如@MyCustomAnnotation
                if (fileContent.contains("@MyCustomAnnotation")) {
                    def className = javaFile.name.replace(".java", "")
                    outputFile.append("Annotated class: $className\n")
                }
            }
        }

        println "注解生成报告已创建:${outputFile.absolutePath}"
    }
}

// 注册任务到Gradle
task generateAnnotationReport(type: AnnotationGeneratorTask)

执行./gradlew generateAnnotationReport就能直接运行你的内联逻辑,完全不依赖外部类。

2. 直接使用doLast闭包(适合简单一次性逻辑)

如果你的代码逻辑不需要复用,直接在普通任务里用doLast闭包写内联代码更简洁:

task generateAnnotationReport {
    doLast {
        def outputFile = file("build/generated/annotations_report.txt")
        outputFile.parentFile.mkdirs()

        sourceSets.main.java.srcDirs.each { srcDir ->
            srcDir.traverse(type: FILES, nameFilter: ~/.*\.java/) { javaFile ->
                if (javaFile.text.contains("@MyCustomAnnotation")) {
                    def className = javaFile.name.replace(".java", "")
                    outputFile.append("Annotated class: $className\n")
                }
            }
        }

        println "注解生成报告已完成"
    }
}

为什么之前的方案失败?

你在build.gradle里定义的MyScript类是Gradle构建脚本自身的类,不属于你的项目编译类路径。而JavaExec任务的作用是运行项目类路径中的主类,所以它找不到这个类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 17:42:40