Groovy MetaProgramming - 拦截所有方法,甚至丢失的方法

标签 groovy metaprogramming

我想拦截类的所有方法(实例和静态),甚至是丢失的方法。

这么说吧:

class SomeClass {
    def methodMissing(String name, args) {
        if(name == "unknownMethod"){
            return "result from unknownMethod"
        }
        else throw new MissingMethodException(name, delegate, args)
    }
}

SomeClass.metaClass.static.invokeMethod = { methodName, args ->
    println "Before"
    def result = delegate.metaClass.invokeMethod(delegate, methodName, *args)
    println "After"
    return result
}

new SomeClass().with{ sc ->
    sc.unknownMethod()  //throw the MissingMethodExcept
}

这对于类实现的方法效果很好,但是当它是由 methodMissing 处理的方法时,我会得到一个 MissingMethodException...

你会怎么做?

提前致谢

最佳答案

我认为您还需要捕获非静态invokeMethod

此外,您需要通过 getMetaMethod 来调用原始方法,否则会有堆栈溢出的风险。

鉴于以下情况:

class SomeClass {
  String name

  static String joinWithCommas( a, b, c ) {
    [ a, b, c ].join( ',' )
  }

  String joinAfterName( a, b, c ) {
    "$name : ${SomeClass.joinWithCommas( a, b, c )}"
  }

  def methodMissing(String name, args) {
    if(name == "unknownMethod"){
      return "result from unknownMethod"
    }
    else {
      throw new MissingMethodException( name, SomeClass, args )
    }
  }
}

// Return a closure for invoke handler for a class
// with a given title (for the logging)
def invokeHandler = { clazz, title ->
  { String methodName, args ->
    println "Before $methodName ($title)"
    def method = clazz.metaClass.getMetaMethod( methodName, args )
    def result = method == null ?
                   clazz.metaClass.invokeMissingMethod( delegate, methodName, args ) :
                   method.invoke( delegate, args )
    println "After $methodName result = $result"
    result 
  }
}

SomeClass.metaClass.invokeMethod = invokeHandler( SomeClass, 'instance' )
SomeClass.metaClass.static.invokeMethod = invokeHandler( SomeClass, 'static' )


new SomeClass( name:'tim' ).with { sc ->
  sc.joinAfterName( 'a', 'b', 'c' )
  sc.unknownMethod( 'woo', 'yay' )
  sc.cheese( 'balls' )
}

我得到输出:

Before with (instance)
Before joinAfterName (instance)
Before joinWithCommas (static)
After joinWithCommas result = a,b,c
After joinAfterName result = tim : a,b,c
Before unknownMethod (instance)
After unknownMethod result = result from unknownMethod
Before cheese (instance)
Exception thrown

groovy.lang.MissingMethodException: No signature of method: SomeClass.cheese() is applicable for argument types: (java.lang.String) values: [balls]

关于Groovy MetaProgramming - 拦截所有方法,甚至丢失的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15898371/

相关文章:

groovy - 如何使用 GrabResolver 在 groovysh 中使用远程存储库

java - @Rule 声明会导致调试尝试出错

groovy - "String toString() { .. }"是什么?

描述符的 Python 元编程 : How to add descriptor after class definition?

ruby 混合和继承注入(inject)

C++结构的自动比较器

web-services - Grails 2.4.4中使用RESTFUL Web服务的登录页面

tomcat - 服务器中显示的日期与我预期的不同

python - 确定描述符中的短运算符(+= like)用法

c++ - Boost.Fusion 运行时开关