Gradle插件中必填配置项需在Extension类中手动校验,推荐在project.afterEvaluate中检查并抛IllegalArgumentException异常,错误信息须具体,且不可依赖@Input/@Optional注解或plugins块实现校验。

Gradle插件里怎么定义必填配置项
插件本身不强制校验「必填」,必须靠你在 Extension 类中手动检查并抛异常。Gradle 不会自动拦截缺失字段,漏写配置只会静默运行、后续出错或行为异常。
在 Extension 类里 throw new IllegalArgumentException
这是最直接也最常用的方式。你定义的 DSL 配置最终映射到一个自定义 Extension 对象(比如 MyPluginExtension),在插件 apply() 执行后期或任务配置阶段主动校验:
- 推荐在校验时机放在
project.afterEvaluate { ... }里——此时所有 build.gradle 中的 DSL 已解析完毕,字段值已确定 - 不要在
Extension构造函数里校验,那时属性还是 null 或默认值,还没被用户赋值 - 错误信息要具体,比如提示缺少
apiToken而不是笼统说“配置不全”
示例片段:
class MyPluginExtension {
String apiToken
File outputDir
}
// 在 apply() 中:
project.extensions.create("myPlugin", MyPluginExtension)
project.afterEvaluate {
def ext = project.extensions.findByType(MyPluginExtension)
if (!ext.apiToken) {
throw new IllegalArgumentException("@myPlugin: 'apiToken' is required but not set")
}
if (!ext.outputDir || !ext.outputDir.isDirectory()) {
throw new IllegalArgumentException("@myPlugin: 'outputDir' must be a valid directory")
}
}
用 @Input + @Optional 注解容易误导
@Input 和 @Optional 是给 Gradle 的增量构建系统看的,和「是否必填」无关。它们只影响缓存键计算和跳过执行逻辑,不会触发校验或报错。
-
@Input表示这个属性参与 task 输入哈希计算,但字段可以为 null -
@Optional是告诉 Gradle “这个输入允许为空”,反而会让 Gradle 放宽处理 - 即使你给
String apiToken加了@Input,用户不设它,插件照样继续跑,直到某处 NPE 或网络请求失败才暴露问题
为什么不在 plugins {} 块里做校验
因为 plugins { id 'com.example.myplugin' version '1.0' } 只负责加载插件类,不触达你的 Extension 实例。配置 DSL(如 myPlugin { apiToken = "xxx" })是在插件 apply 后由 Gradle 解析并设置到 extension 实例上的,二者是分离的阶段。
这意味着:你不能靠 plugins 块语法本身来约束必填项;必须等 extension 被构造、被赋值、且项目配置完成之后,再动手检查。
最容易被忽略的是校验时机 —— 早了(比如在 extension 构造时)拿不到值,晚了(比如等到某个 task 执行时)错误堆栈深、定位困难。统一收口到 afterEvaluate 是目前最稳妥的做法。











