代码之家  ›  专栏  ›  技术社区  ›  Daff

使用invokemethod在groovy中动态实现接口

  •  5
  • Daff  · 技术社区  · 15 年前

    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()
        }
    }
    

    返回闭包很好,但我找不到一种方法来找出在那里调用的方法的名称。

    尝试对此引用本身进行代理(以便方法调用将调用InvokeMethod)时返回空值。

    2 回复  |  直到 15 年前
        1
  •  9
  •   Christoph Metzendorf    15 年前

    可以使用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)
    }
    
        2
  •  0
  •   user1052797    15 年前

    完成Christoph的回复,如本文所述 page ,您可以实现一个带有闭包的接口。例如:

    def map = [doBla: { println 'Bla!'}, hello: {world -> "Hello $world".toString()}] as TestInterface
    map.hello 'Groovy' // returns 'Hello Groovy'