Gradle 最近引入了一个用于延迟配置的 API ,现在插件扩展和任务类型等内部功能已迁移到这个新 API。总之,可以说(几乎)构建脚本中的每个配置属性都应该使用Property<T>
or Provider<T>
(只读)而不是简单类型的 getter 和 setter 来实现T
。为了提供向后兼容性,很多属性没有改变,但添加了新属性,旧属性读取和写入这些新属性。
这也是您的问题的情况,因为BootRun
Spring Boot Gradle 插件中的JavaExec
任务类型扩展了 Gradle 提供的任务类型。添加了新属性mainClass
(a Property<string>
),并main
修改了旧属性以使用新属性。该方法从using中getMain()
读取,而在使用 Groovy 中的语法时调用的 method写入using 。mainClass
Property.get()
setMain(String)
main = '...'
mainClass
Property.set(String)
这一切都可以正常工作,但 Gradle 为他们的惰性配置 API 引入了一些额外的功能。这些特性之一是可写属性的最终确定(Property<>
)。在构建的某个时间点,mainClass
将读取任务属性(例如 )以用于其原始目的(运行任务),因此在该点之后的任何更改都不会生效。在早期版本的 Gradle 中,这会导致很多难以调试的问题,因为 Gradle 不会显示任何错误。现在,一旦这些属性被读取以用于其原始目的,它们就会被最终确定,当有人试图在之后更改它们时导致 Gradle 失败。
关于您的用例,属性mainClass
(由 访问main
)已经在doFirst
闭包中完成,因此您需要提前应用此配置。由于您要将值设置为属性的值bootJar.mainClassName
(这是一个简单的String
),因此您必须确保在读取此属性以配置bootRunB
任务之前具有其最终值:
bootJar {
mainClassName = '...'
}
task bootRunB(type: org.springframework.boot.gradle.tasks.run.BootRun, dependsOn: 'build') {
group = 'Application'
main = bootJar.mainClassName
// From this point, bootRun.classpath must not be changed !
classpath = bootRun.classpath
systemProperty '...'
}
为了消除对配置顺序的依赖,你可以创建一个Provider<String>
using Project.provider(...)
:
task bootRunB(type: org.springframework.boot.gradle.tasks.run.BootRun, dependsOn: 'build') {
group = 'Application'
main = provider({ bootJar.mainClassName })
classpath = bootRun.classpath
systemProperty '...'
}