让我们说我们有一个带有一些方法(静态或非静态)的groovy类。 我想要做的是在调用此类的每个方法之前和之后执行一些代码,而根本不需要触及类,也不需要动态操作每个方法中的代码。
我尝试使用groovy metaClass;获取metaClass的所有方法,然后使用包装方法动态替换every方法,包含一些代码,并在中间调用旧方法。问题是,我不知道每个原始方法的参数,所以我不能用新方法(闭包)替换旧方法,因为我无法动态创建具有不同数量和类型参数的包装闭包,即使我可以,我不知道如何在包装封口内访问它们。我需要包装闭包具有旧方法的相同签名,以便在有人在透明地更改类之后尝试调用旧方法时调用闭包。
在Javascript中,例如我可以使用args []数组访问函数体中的所有参数,即使我在编写代码时不知道参数名称。
我怎样才能在groovy中这样做?或者他们可能是另一种实现我尝试做的方式?
答案 0 :(得分:7)
下面会有什么作用?使用invokeMethod
拦截对每个方法的调用。测试是不言自明的。
<强>解释强>
下面的metaClass实现会覆盖GroovyObject
的invokeMethod。由于所有groovy对象都继承自GroovyObject,因此我们可以灵活地操作/拦截方法调用,甚至可以指定我们自己的methodMissing
实现。我们需要一个覆盖静态方法和一个非静态方法。基本上,invokeMethod拦截对定义它的Class上的每个方法的调用。我们最终为每种方法提供了一些before
和after
功能。使用反射,下面的实现能够通过名称和参数找出方法,并在运行时调用它。
注意: -
<强>实施强>
class Dummy {
def method1() { System.out.println "In method 1" }
def method2(String str) { System.out.println "In method 2" }
static def method3(int a, int b) {
System.out.println "In static method 3"
}
}
Dummy.metaClass.invokeMethod = {String name, args ->
def result
System.out.println(
"Do something before $name is called with args $args")
try {
result = delegate.metaClass.getMetaMethod(name, args)
.invoke(delegate, args)
} catch(Exception e) {
System.out.println "Handling exception for method $name"
}
System.out.println(
"Do something after $name was called with args $args \n")
result
}
Dummy.metaClass.'static'.invokeMethod = {String name, args ->
def result
System.out.println(
"Do something before static method $name is called with args $args")
try {
result = delegate.metaClass.getMetaMethod(name, args)
.invoke(delegate, args)
} catch(Exception e) {
System.out.println "Handling exception for method $name"
}
System.out.println(
"Do something after static method $name was called with args $args \n")
result
}
def dummy = new Dummy()
dummy.method1()
dummy.method2('Test')
Dummy.method3(1, 2)