【问题标题】:Dynamically implement interface in Groovy using invokeMethod在 Groovy 中使用 invokeMethod 动态实现接口
【发布时间】:2010-12-18 10:31:40
【问题描述】:

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

返回闭包可以正常工作,但我无法找到一种方法来找出在那里调用的方法的名称。

尝试对 this 引用本身进行代理(以便方法调用将调用 invokeMethod)返回 null。

【问题讨论】:

    标签: reflection dynamic groovy interface


    【解决方案1】:

    page 所述,要完成Christoph 的响应,您可以实现一个带有闭包的接口。例如:

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

    【讨论】:

      【解决方案2】:

      您可以使用 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)
      }
      

      【讨论】:

      • 非常感谢,工作起来就像一个魅力,看起来很干净,我仍然可以访问所有成员变量和方法。
      • 就目前而言,这不适用于具有重载方法的接口。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-17
      • 2016-04-11
      • 2012-04-24
      • 2011-03-30
      • 2011-02-27
      • 2015-03-07
      • 1970-01-01
      相关资源
      最近更新 更多