2013-04-09 36 views
2

我想攔截一個類的所有方法(實例和靜態),即使是丟失的方法。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方法...

你會怎麼做那?

在此先感謝

回答

2

我認爲你需要趕上非靜態invokeMethod以及

此外,您還需要經過getMetaMethod調用原始方法,否則你運行stackoverflows的風險。

考慮以下幾點:

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] 
+0

我嘗試,並讓你知道 – Fiftoine 2013-04-09 10:41:06

+0

的問題保持不變,當方法未實現,但被處理通過methodMissing,getMetaMethod返回null,但調用它沒有攔截返回的東西... – Fiftoine 2013-04-09 10:49:36

+0

@Fiftoine哦...你*想*一個'MissingMethodException拋出? – 2013-04-09 10:50:42