【问题标题】:Groovy - How do I use metaprogramming to add tracing to all static methods of a class?Groovy - 如何使用元编程将跟踪添加到类的所有静态方法?
【发布时间】:2011-01-20 00:51:58
【问题描述】:

这是我目前所拥有的:

static def traceMethods(Class clazz) {
    def mc = clazz.metaClass

    mc.static.invokeMethod = { String name, args ->
        List types = args.collect { it == null ? null : it.getClass() }
        MetaMethod metmeth = mc.getStaticMetaMethod(name, *types) //throws exception sometimes when it shouldnt

        println "Starting method $name"
        def result = metmeth.doMethodInvoke(delegate, args)         
        println "Finished method $name"

        return result
    }
}

这在大多数情况下都能完美运行。但是,有时对getStaticMetaMethod 的调用会在不应该抛出异常时抛出异常。

编辑:它抛出的异常是:

 groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method org.codehaus.groovy.runtime.HandleMetaClass#getStaticMetaMethod.|Cannot resolve which method to invoke for [class java.lang.String, null] due to overlapping prototypes between:|?[class java.lang.String, class [Ljava.lang.Object;]|?[class java.lang.String, class [Ljava.lang.Class;]
    at groovy.lang.MetaClassImpl.chooseMostSpecificParams(MetaClassImpl.java:2906)
    at groovy.lang.MetaClassImpl.chooseMethodInternal(MetaClassImpl.java:2859)
    at groovy.lang.MetaClassImpl.chooseMethod(MetaClassImpl.java:2800)
    at groovy.lang.MetaClassImpl.getMethodWithCachingInternal(MetaClassImpl.java:1181)
    at groovy.lang.MetaClassImpl.createPogoCallSite(MetaClassImpl.java:3022)

【问题讨论】:

  • @lgs - 我编辑了我的问题以包含异常

标签: groovy metaprogramming


【解决方案1】:

您的意思是改为执行以下操作吗?

MetaMethod metmeth = mc.getStaticMetaMethod(name, types as Class[])

假设 args 是 [1,"abc",true]。这将导致types 成为[Integer,String,Boolean]

在此处使用扩展运算符 (*) 会导致 Groovy 尝试调用具有类似 getStaticMetaMethod(String,Integer,String,Boolean) 的签名的方法。这可能不是你想要的。

但是,由于没有该签名的方法,Groovy 回退到尝试将*type 转换为适当的类似集合的对象。在这种情况下,它可以选择Class[]Object[],因为getStaticMetaMethod(String,Class[])getStaticMetaMethod(String,Object[]) 方法都存在。

当 args 只包含一个空值时,Groovy 无法决定是转换为 Class[] 还是 Object[],因此会出现异常。使用显式转换 (types as Class[]) 可以让 Groovy 清楚您的意图并消除歧义。

顺便说一句,您可以使用原始代码重现异常,并且:

class A {
    static def doX(String s) { }
}
traceMethods(A)
A.doX(null)

【讨论】:

    猜你喜欢
    • 2010-11-30
    • 2011-01-30
    • 2013-02-02
    • 2011-03-22
    • 2013-01-16
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多