Micronaut自定义验证问题:AnnotationValue不支持Closures
问题原因分析
- 注解参数类型与实际传入不匹配:你的
@NotNullIf注解定义value()返回Class<? extends Closure<Boolean>>,但使用时直接传入了闭包实例({ Cust obj -> obj.type != CustType.NONE }),而非闭包的Class对象。注解参数仅支持常量、Class、枚举等编译期可确定的类型,直接传闭包实例会导致AnnotationValue无法正确解析该参数。 - AnnotationValue获取逻辑错误:你尝试直接获取
Closure实例,但注解中实际存储的是Class对象,类型不匹配导致获取失败;同时使用字符串'value'获取参数的方式不够可靠,容易出现拼写错误。
修正步骤
1. 调整注解使用方式
将闭包转换为可引用的Class对象,Groovy中可以提取为静态闭包后获取其Class:
@Introspected class Cust { @NotNull CustType type // 提取为静态闭包,便于获取Class对象 static final Closure<Boolean> CHECK_TYPE_NOT_NONE = { Cust obj -> obj.type != CustType.NONE } @NotNullIf(value = CHECK_TYPE_NOT_NONE.class) String optional }
2. 修正ConstraintValidator实现
从注解中获取闭包的Class,实例化后再执行逻辑:
import io.micronaut.core.annotation.AnnotationValue import io.micronaut.core.annotation.NonNull import io.micronaut.core.annotation.Nullable import io.micronaut.validation.validator.constraints.ConstraintValidator import io.micronaut.validation.validator.constraints.ConstraintValidatorContext import jakarta.inject.Singleton import groovy.util.logging.Slf4j @Singleton @Slf4j class NotNullIfConstraint implements ConstraintValidator<NotNullIf, Object> { @Override boolean isValid(@Nullable Object value, @NonNull AnnotationValue<NotNullIf> annotationMetadata, @NonNull ConstraintValidatorContext context) { // 类型安全地获取闭包Class Class<? extends Closure<Boolean>> closureClass = annotationMetadata.getValue(NotNullIf::value) .orElseThrow(() -> new IllegalArgumentException("NotNullIf missing value()")) // 实例化闭包 Closure<Boolean> shouldEvaluateNotNull = closureClass.newInstance() // 传入根Bean执行闭包判断 boolean evaluateNotNull = shouldEvaluateNotNull.call(context.rootBean) return evaluateNotNull ? value != null : true } }
3. 可选:改用更简洁的Micronaut原生方式
Micronaut支持通过@AssertTrue结合类方法实现条件验证,无需自定义注解,更符合框架规范:
@Introspected class Cust { @NotNull CustType type String optional @AssertTrue(message = "validation.not.null.if.message") boolean isOptionalValid() { return type == CustType.NONE || optional != null } }
额外注意事项
- 确保已正确引入核心依赖:
implementation("io.micronaut.validation:micronaut-validation") implementation("io.micronaut.groovy:micronaut-groovy")
内容的提问来源于stack exchange,提问作者sbglasius
相关产品推荐
相关产品推荐

