基于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
相关产品推荐
相关产品推荐

