Groovy—如何使用元编程向类的所有静态方法添加跟踪?

Groovy—如何使用元编程向类的所有静态方法添加跟踪?,groovy,metaprogramming,Groovy,Metaprogramming,这就是我到目前为止所做的: 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.getStati

这就是我到目前为止所做的:

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)

你是不是打算做以下的事情

MetaMethod metmeth = mc.getStaticMetaMethod(name, types as Class[])
假设args是[1,abc,true]。这将导致类型为[Integer、String、Boolean]

在这里使用扩展运算符*会导致Groovy尝试调用带有签名的方法,如getStaticMetaMethodString、Integer、String、Boolean。那可能不是你想要的

但是,由于没有该签名的方法,Groovy转而尝试将*type转换为适当的集合(如对象)。在本例中,它具有类[]或对象[]的选项,因为方法getStaticMetaMethodString、类[]和getStaticMetaMethodString、对象[]都存在

当args仅包含空值时,Groovy无法决定是转换为类[]还是对象[],因此会出现异常。使用显式转换类型作为类[]可以让Groovy清楚地了解您的意图并消除歧义

顺便说一下,您可以使用原始代码复制异常,并且:

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

@lgs-我编辑了我的问题以包含例外情况