1. 引言
本文将探索三种在构建时读取Gradle文件中定义变量的方法。当Java代码需要根据构建配置改变行为时,这个技巧特别实用——我们只需在Gradle中定义一次变量,避免在Java和Gradle中重复定义。我们将通过代码生成和变量注入两种方式解决这个问题。
2. 生成Java类
首先定义Gradle变量:
ext {
myVersion = '1.2.3'
}
✅ 通过构建时生成代码,能让Gradle变量在Java中访问
第一种方案是创建包含静态变量的final类。首先将生成目录加入编译路径:
def generatedDir = "$buildDir/generated-src"
sourceSets {
main {
java {
srcDirs += "$generatedDir"
}
}
}
然后定义Gradle任务生成BuildConfig.java
文件:
tasks.register('generateBuildConfig') {
doLast {
def outputDir = file("$generatedDir/com/baeldung/gradle/config")
outputDir.mkdirs()
def file = new File(outputDir, "BuildConfig.java")
file.text = """
package com.baeldung.gradle.config;
public final class BuildConfig {
public static final String MY_VERSION = "${myVersion}";
private BuildConfig() {}
}
""".stripIndent()
}
}
这个文件可以包含任意数量变量——这里我们只读取预定义的myVersion
。执行generateBuildConfig
任务后,将在build/generated-src/com/baeldung/gradle/config
目录生成:
package com.baeldung.gradle.config;
public final class BuildConfig {
public static final String MY_VERSION = "1.2.3";
private BuildConfig() {}
}
由于已将generated-src
加入项目源路径,可直接通过静态成员访问:
assertEquals("1.2.3", BuildConfig.MY_VERSION);
最后将任务加入构建流程:
compileJava.dependsOn generateBuildConfig
这样确保compileJava
在generateBuildConfig
之后执行。
3. 生成属性文件
第二种方案是构建时生成properties文件。这种方法与上一种类似,但输出和读取方式不同。
首先将生成目录加入资源路径:
def generatedResourcesDir = "$buildDir/generated-resources"
sourceSets {
main {
resources {
srcDirs += "$generatedResourcesDir"
}
}
}
然后定义generateProperties
任务:
tasks.register('generateProperties') {
doLast {
def mainResourcesDir = file("$generatedResourcesDir/main")
mainResourcesDir.mkdirs()
def mainFile = file("$mainResourcesDir/version.properties")
mainFile.text = "MY_VERSION=${myVersion}"
}
}
此任务在build/generated-resources/main
目录生成version.properties
文件:
MY_VERSION=1.2.3
使用Properties
类读取文件:
Properties props = new Properties();
props.load(Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("version.properties"));
String version = props.getProperty("MY_VERSION");
assertEquals("1.2.3", version);
同样需要设置任务依赖:
compileJava.dependsOn generateProperties
确保generateProperties
在compileJava
前执行。
4. 注入为环境或系统属性
⚠️ 最简单粗暴的方法:注入为环境或系统属性。需要为特定任务指定注入变量。
以test
任务为例:
test {
systemProperty "MY_VERSION", "${myVersion}"
environment "MY_VERSION", "${myVersion}"
}
其他任务(如bootRun
)同样适用。读取方式极其简单:
assertEquals("1.2.3", System.getProperty("MY_VERSION"));
assertEquals("1.2.3", System.getenv("MY_VERSION"));
✅ 无需调整任务执行顺序,这是此方案的优势。
5. 总结
本文讨论了三种在Java中读取Gradle变量的方法,各有适用场景:
- 常量代码生成:编译时检查,减少运行时错误
- 属性文件生成:适合资源类配置
- 运行时注入:最动态的方案,理论上无需重启应用即可更新变量值
⚠️ 踩坑提示:选择方案时需权衡编译安全性和运行时灵活性需求。生产环境推荐前两种方案,开发调试可用第三种。
完整示例代码见GitHub仓库。