Groovy如何在ASTTransformationCustomizer中覆盖@TimedInterrupt时间单位
原因说明
ASTTransformationCustomizer在构造注解的AST节点时,要求传入的所有注解参数必须是Groovy编译器可识别的表达式节点,你之前尝试的传参方式不符合这个要求:
- 直接传入
TimeUnit.MILLISECONDS枚举实例:自定义器不会自动将运行时的Java枚举对象转换为编译期AST节点,编译器会判定该值为非法常量 - 传入
ConstantExpression实例:ConstantExpression仅支持表示字符串、数字、布尔值这类基础字面量,无法承载枚举类型值 - 传入字符串形式的枚举名/全类名:自定义器不会自动完成字符串到枚举的类型转换,参数类型和注解定义的
TimeUnit类型不匹配,会直接触发编译器内部异常
正确实现代码
手动构造对应枚举值的属性表达式节点,和直接在Groovy脚本中编写TimeUnit.MILLISECONDS生成的AST结构完全一致即可正常生效,示例如下:
import org.codehaus.groovy.ast.expr.PropertyExpression; import java.util.concurrent.TimeUnit; import static org.codehaus.groovy.ast.tools.GeneralUtils.classX; import static org.codehaus.groovy.ast.tools.GeneralUtils.propX; var config = new CompilerConfiguration(); var timedInterruptParams = new HashMap<String, Object>(); timedInterruptParams.put("value", myTimeout); // 构造目标时间单位对应的AST表达式 PropertyExpression targetUnitExpr = propX( classX(TimeUnit.class), TimeUnit.MILLISECONDS.name() // 替换为你需要的时间单位枚举名即可 ); timedInterruptParams.put("unit", targetUnitExpr); config.addCompilationCustomizers( new ASTTransformationCustomizer(CompileStatic.class), new ASTTransformationCustomizer(timedInterruptParams, TimedInterrupt.class) );
如果需要切换其他时间单位,只需要将TimeUnit.MILLISECONDS替换为对应的枚举值,比如TimeUnit.SECONDS、TimeUnit.MINUTES,不需要修改其他逻辑。
内容的提问来源于stack exchange,提问作者Martin Häusler
相关产品推荐
相关产品推荐

