使用invokeMethod在Groovy中动态实现接口

Daf*_*aff 5 reflection groovy interface dynamic

Groovy提供了一些非常简洁的语言功能来处理和实现Java接口,但我似乎有些困惑.

我想在Groovy类上动态实现一个接口,并使用GroovyInterceptable.invokeMethod拦截该接口上的所有方法调用.这是我到目前为止所尝试的:

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

返回Closure工作正常,但我无法想办法找出在那里调用的方法的名称.

尝试为此引用本身创建一个代理(以便方法调用将调用invokeMethod)返回null.

Chr*_*orf 9

您可以使用Groovy的Map强制功能动态生成表示给定接口的Map:

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)
}
Run Code Online (Sandbox Code Playgroud)