BuildService是Gradle 6.1引入的构建内资源复用机制,用于在单次构建(含所有子项目)中安全共享昂贵资源,需在插件apply阶段注册,实现AutoCloseable以自动释放,不跨构建或daemon进程共享。

BuildService 是 Gradle 6.1 引入的机制,用于在构建生命周期中安全、高效地复用昂贵资源(比如数据库连接、编译器实例、缓存对象等),它替代了过去靠 project.extra 或静态单例手动管理的反模式。但要注意:BuildService 本身不跨项目共享,只在单次构建(包括所有子项目)内共享——它不是为“多 project 间长期共享”设计的,也不是 buildSrc 的替代品。
BuildService 的作用域和生命周期很关键
- 它绑定到当前
Gradle实例(即一次./gradlew build执行),所有子项目任务都能访问同一个服务实例 - 服务在构建开始时创建,构建结束时由 Gradle 自动关闭(调用
close(),前提是实现了AutoCloseable) - 不支持跨 Gradle daemon 进程共享,也不持久化到磁盘;每次新构建都是新实例
- 不能在
settings.gradle中注册(那里还没加载插件),必须在插件的apply()阶段或project.afterEvaluate后注册
怎么在自定义插件里注册并使用 BuildService
你得先定义一个服务类,再通过 project.getGradle().getSharedServices().registerIfAbsent() 注册:
- 服务类必须:
- 是 public class
- 有 public 无参构造函数(或带
@Inject构造函数,且参数可被 Gradle 注入,如ProviderFactory) - 可选实现
AutoCloseable以释放资源
- 注册时需指定唯一名称(
String)和类型(Class),后续都靠这个名字获取
class MyResourceService implements AutoCloseable {
final Map<string object> cache = new ConcurrentHashMap();
<pre class="brush:java;toolbar:false;">@Override
void close() {
println "MyResourceService closed"
}
}
class MyPlugin implements Plugin
注意:上面的 service.get() 返回的是线程安全的代理对象,不是原始实例——Gradle 会做同步和生命周期代理。
常见错误和坑点
-
误以为能跨构建共享:重启 daemon 或换命令(如从
build改成test)就会新建服务实例,缓存清空 -
在
configureEach或withType里重复注册:会导致注册失败(同名服务已存在),应确保只注册一次,推荐放在插件apply最外层 -
服务类用了不可序列化的字段(如
ThreadLocal、Socket)却没处理关闭逻辑:可能引发内存泄漏或构建卡死 -
在
settings或init脚本里尝试注册:会抛UnsupportedOperationException,因为此时sharedServices尚未初始化
BuildService 的价值不在“跨项目”,而在“跨任务复用”——尤其适合需要初始化成本高、但读写轻量的场景,比如 JSON Schema 校验器、本地 HTTP mock server、AST 缓存池。如果目标是让多个独立 Git 仓库共用同一套版本定义或插件逻辑,那该用 buildSrc 发布为二进制插件,或走 Composite Build,而不是硬塞 BuildService。











