自定义Gradle插件中如何在任务内正确配置任务依赖
解决方案
你遇到的是Gradle生命周期时机匹配的典型问题,核心是要把依赖绑定逻辑放在配置解析完成后、任务依赖图构建前的节点执行,不要放在任务构造函数或者任务执行方法里。
推荐实现:使用afterEvaluate生命周期回调
project.afterEvaluate会在当前项目所有build.gradle配置代码全部执行完成、所有用户设置的任务属性都赋值完毕之后触发,此时还没进入任务依赖图构建和执行阶段,是绑定按需依赖的最佳时机。
你不需要把依赖逻辑写到BaseProjectTask类内部,直接在插件的apply方法中注册回调即可:
// 插件apply方法内的逻辑 @Override void apply(Project project) { // 懒注册所有内置子任务,不提前创建实例减少配置开销 def copyDockerResTask = project.tasks.register('copyDockerResources', CopyDockerResourcesTask) def copyContainerTask = project.tasks.register('copyContainerFiles', CopyContainerFilesTask) def analysisTask = project.tasks.register('performAnalysis', PerformAnalysisTask) // 注册主任务 def baseTask = project.tasks.register('BaseProjectTask', BaseProjectTask) // 等所有用户配置解析完成后再绑定依赖 project.afterEvaluate { BaseProjectTask config = baseTask.get() // 按需绑定依赖:既可以挂到assemble上,也可以挂到baseTask上保证执行主任务时触发子任务 if (config.copyContainerFiles) { project.tasks.named('assemble').configure { dependsOn copyContainerTask } baseTask.configure { dependsOn copyContainerTask } } if (config.copyDockerResources) { project.tasks.named('assemble').configure { dependsOn copyDockerResTask } baseTask.configure { dependsOn copyDockerResTask } } if (config.performAnalysis) { project.tasks.named('assemble').configure { dependsOn analysisTask } baseTask.configure { dependsOn analysisTask } } } }
注意:优先用
tasks.register做懒任务注册,不要用tasks.create,可以避免未开启的任务产生不必要的配置开销,符合Gradle性能最佳实践。
更规范的优化:用扩展类承载配置
把配置开关直接写在任务类上不是Gradle插件的常规设计,更推荐单独定义Extension扩展类存放配置项,用Property类型做懒属性绑定,默认值设为false即可完全匹配你预期的配置写法,还能更好支持Gradle的构建缓存、配置缓存特性:
abstract class BaseProjectExtension { abstract Property<Boolean> copyDockerResources abstract Property<Boolean> copyContainerFiles abstract Property<Boolean> performAnalysis BaseProjectExtension() { // 设置默认值,默认不开启任何功能 copyDockerResources.convention(false) copyContainerFiles.convention(false) performAnalysis.convention(false) } }
在插件apply方法中注册扩展即可,用户在build.gradle里的配置写法和你原来的设计完全一致,不需要做任何改动。
原有写法失效原因
- 依赖逻辑写在
@TaskAction标注的方法中时,Gradle已经完成任务依赖图构建,进入了任务执行阶段,此时新增的依赖不会被加入执行图,自然不会触发对应任务。 - 依赖逻辑写在任务构造函数中时,Gradle还未解析build.gradle里给任务设置的属性值,你拿到的永远是初始默认值false,无法实现按需开启的效果。
内容的提问来源于stack exchange,提问作者Wiktor
相关产品推荐
相关产品推荐

