Groovy 使用自定义注解执行代码
Groovy execute code using custom annotation
我想通过 groovy 脚本中的注释标记执行函数(带参数)。
如果我们使用此注释在 groovy 脚本中执行一个方法,它将在控制台 (stderr) 中打印一条自定义消息,例如:
warning: '<function_name>' is deprecated [[Use '<Deprecated.instead>' instead.][More info: '<Deprecated.more_info>']]
所以,我创建了一个这样的自定义注释
public @interface Deprecated {
public String instead() default null
public String more_info() default null
}
目标是这样使用它:
def new_call() {
//new version of the method
}
@Deprecated(instead="new_call")
def call() {
//do something
}
在我的示例中,它会输出如下:
warning: 'call' is deprecated. Use 'new_call' instead.
我看到了这个 post Groovy: How to call annotated methods,它现在已经 7 年多了,但看起来不错,所以我会看得更深。
我也看到了 Delegate.deprecated 但我不确定这是否是我想要的
我不确定我做得对不对。因此,如果您有任何意见或建议,我将很高兴听到您的意见。
简单的 AOP 方法
这是 very-very 使用 groovy out-of 框的基本实现。
弃用注释
@Target([ElementType.METHOD])
@Retention(RetentionPolicy.RUNTIME)
@interface Deprecated {
String instead() default 'null'
String more_info() default 'null'
}
Class 应具有此功能
class 必须实施 GroovyInterceptable
- invokeMethod
。
class SomeClass implements GroovyInterceptable {
@Override
def invokeMethod(String name, args) {
DeprecatedInterception.apply(this, name, args)
}
def new_call() {
println('new_call invoked')
}
@Deprecated(instead = 'new_call', more_info = '... the reason')
def depr_call() {
println('depr_call invoked')
}
}
拦截实用程序
import org.codehaus.groovy.reflection.CachedMethod
class DeprecatedInterception {
static apply(Object owner, String methodName, Object args) {
MetaMethod metaMethod = owner.metaClass.getMetaMethod(methodName, args)
Deprecated d = extractAnnotation(metaMethod)
if (d) {
println("warning: '$methodName' is deprecated. Use '${d.instead()}' instead. More info: '${d.more_info()}'")
}
// handle methods with var-args
metaMethod.isVargsMethod() ?
metaMethod.doMethodInvoke(owner, args) :
metaMethod.invoke(owner, args)
}
static Deprecated extractAnnotation(MetaMethod metaMethod) {
if (metaMethod instanceof CachedMethod) {
metaMethod.getCachedMethod()?.getAnnotation(Deprecated)
} else {
null
}
}
}
简单测试
检查没有exceptions/errors..
class TestWarnings {
@Test
void test() {
new SomeClass().with {
new_call()
depr_call()
}
}
}
输出:
new_call invoked
warning: 'depr_call' is deprecated. Use 'new_call' instead. More info: '... the reason'
depr_call invoked
免责声明
这应该适用于大多数情况,但有一些限制:
- 不适用于静态方法(除非在 Object 实例上调用)
- 您必须为每个 class 实施
GroovyInterceptable
,才能申请
- 您可能在某些 groovy 语法或功能中遇到了一些 side-effects(至少我发现了 vararg 方法调用的问题,但这已经修复)[=63=]
因此,在广泛用于某些生产项目之前,应该对其进行测试并可能进行改进。
其他选项:
很快,因为实现可能会更复杂(不确定,至少我不能在短时间内提供一些示例),但这可能更可靠。
- 添加 AST 转换。
- 使用一些 AOP 库。
我想通过 groovy 脚本中的注释标记执行函数(带参数)。 如果我们使用此注释在 groovy 脚本中执行一个方法,它将在控制台 (stderr) 中打印一条自定义消息,例如:
warning: '<function_name>' is deprecated [[Use '<Deprecated.instead>' instead.][More info: '<Deprecated.more_info>']]
所以,我创建了一个这样的自定义注释
public @interface Deprecated {
public String instead() default null
public String more_info() default null
}
目标是这样使用它:
def new_call() {
//new version of the method
}
@Deprecated(instead="new_call")
def call() {
//do something
}
在我的示例中,它会输出如下:
warning: 'call' is deprecated. Use 'new_call' instead.
我看到了这个 post Groovy: How to call annotated methods,它现在已经 7 年多了,但看起来不错,所以我会看得更深。 我也看到了 Delegate.deprecated 但我不确定这是否是我想要的
我不确定我做得对不对。因此,如果您有任何意见或建议,我将很高兴听到您的意见。
简单的 AOP 方法
这是 very-very 使用 groovy out-of 框的基本实现。
弃用注释
@Target([ElementType.METHOD])
@Retention(RetentionPolicy.RUNTIME)
@interface Deprecated {
String instead() default 'null'
String more_info() default 'null'
}
Class 应具有此功能
class 必须实施 GroovyInterceptable
- invokeMethod
。
class SomeClass implements GroovyInterceptable {
@Override
def invokeMethod(String name, args) {
DeprecatedInterception.apply(this, name, args)
}
def new_call() {
println('new_call invoked')
}
@Deprecated(instead = 'new_call', more_info = '... the reason')
def depr_call() {
println('depr_call invoked')
}
}
拦截实用程序
import org.codehaus.groovy.reflection.CachedMethod
class DeprecatedInterception {
static apply(Object owner, String methodName, Object args) {
MetaMethod metaMethod = owner.metaClass.getMetaMethod(methodName, args)
Deprecated d = extractAnnotation(metaMethod)
if (d) {
println("warning: '$methodName' is deprecated. Use '${d.instead()}' instead. More info: '${d.more_info()}'")
}
// handle methods with var-args
metaMethod.isVargsMethod() ?
metaMethod.doMethodInvoke(owner, args) :
metaMethod.invoke(owner, args)
}
static Deprecated extractAnnotation(MetaMethod metaMethod) {
if (metaMethod instanceof CachedMethod) {
metaMethod.getCachedMethod()?.getAnnotation(Deprecated)
} else {
null
}
}
}
简单测试
检查没有exceptions/errors..
class TestWarnings {
@Test
void test() {
new SomeClass().with {
new_call()
depr_call()
}
}
}
输出:
new_call invoked
warning: 'depr_call' is deprecated. Use 'new_call' instead. More info: '... the reason'
depr_call invoked
免责声明
这应该适用于大多数情况,但有一些限制:
- 不适用于静态方法(除非在 Object 实例上调用)
- 您必须为每个 class 实施
GroovyInterceptable
,才能申请 - 您可能在某些 groovy 语法或功能中遇到了一些 side-effects(至少我发现了 vararg 方法调用的问题,但这已经修复)[=63=]
因此,在广泛用于某些生产项目之前,应该对其进行测试并可能进行改进。
其他选项:
很快,因为实现可能会更复杂(不确定,至少我不能在短时间内提供一些示例),但这可能更可靠。
- 添加 AST 转换。
- 使用一些 AOP 库。