Reflection 使用invokeMethod在Groovy中动态实现接口
Groovy为处理和实现Java接口提供了一些非常简洁的语言特性,但我似乎有点卡住了 我想在Groovy类上动态实现一个接口,并使用GroovyInterceptable.invokeMethod拦截该接口上的所有方法调用。以下是我迄今为止所做的尝试:Reflection 使用invokeMethod在Groovy中动态实现接口,reflection,dynamic,groovy,interface,Reflection,Dynamic,Groovy,Interface,Groovy为处理和实现Java接口提供了一些非常简洁的语言特性,但我似乎有点卡住了 我想在Groovy类上动态实现一个接口,并使用GroovyInterceptable.invokeMethod拦截该接口上的所有方法调用。以下是我迄今为止所做的尝试: public interface TestInterface { public void doBla(); public String hello(String world); } import groovy.lang.Gro
public interface TestInterface
{
public void doBla();
public String hello(String world);
}
import groovy.lang.GroovyInterceptable;
class GormInterfaceDispatcher implements GroovyInterceptable
{
def invokeMethod(String name, args) {
System.out.println ("Beginning $name with $args")
def metaMethod = metaClass.getMetaMethod(name, args)
def result = null
if(!metaMethod)
{
// Do something cool here with the method call
}
else
result = metaMethod.invoke(this, args)
System.out.println ("Completed $name")
return result
}
TestInterface getFromClosure()
{
// This works, but how do I get the method name from here?
// I find that even more elegant than using invokeMethod
return { Object[] args -> System.out.println "An unknown method called with $args" }.asType(TestInterface.class)
}
TestInterface getThisAsInterface()
{
// I'm using asType because I won't know the interfaces
// This returns null
return this.asType(TestInterface.class)
}
public static void main(String[] args)
{
def gid = new GormInterfaceDispatcher()
TestInterface ti = gid.getFromClosure()
assert ti != null
ti.doBla() // Works
TestInterface ti2 = gid.getThisAsInterface()
assert ti2 != null // Assertion failed
ti2.doBla()
}
}
返回闭包可以很好地工作,但是我找不到一种方法来找出在那里调用的方法的名称
尝试对此引用本身进行代理(以便方法调用将调用invokeMethod)返回null。您可以使用Groovy的映射强制功能动态生成表示给定接口的映射:
TestInterface getMapAsInterface() {
def map = [:]
TestInterface.class.methods.each() { method ->
map."$method.name" = { Object[] args->
println "Called method ${method.name} with ${args}"
}
}
return map.asType(TestInterface.class)
}
如本文所述,要完成Christoph的响应,您可以使用闭包实现一个接口。例如:
def map = [doBla: { println 'Bla!'}, hello: {world -> "Hello $world".toString()}] as TestInterface
map.hello 'Groovy' // returns 'Hello Groovy'
非常感谢,它很有魅力,看起来很干净,我仍然可以访问所有的成员变量和方法。