3

我正在尝试检查来自 Java 的一些 CGLib 代理 Groovy 类上的 Groovy 生成方法,以了解方法的返回和参数类型。例如,考虑这个 Groovy 类:

class Person {
  String name
}

Groovy 为 name 属性生成getName()setName()方法。getName()大概返回 aString并且setName()大概需要 a String

但是当通过 CGLib 代理这个类并拦截对getName使用 CGLib 的MethodInterceptor的调用时,method.getName()返回getMetaClassmethod.getReturnType()返回groovy.lang.MetaClass

有没有办法从MethodInterceptor中学习实际的方法名称和返回类型?

编辑:这是拦截 Person.getName() 调用时的调用堆栈:

ExplicitMappingInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 42    
GroovyMMTester$A$$EnhancerByCGLIB$$915b5b4.getMetaClass() line: not available   
CallSiteArray.createPogoSite(CallSite, Object, Object[]) line: 144  
CallSiteArray.createCallSite(CallSite, Object, Object[]) line: 161  
CallSiteArray.defaultCall(CallSite, Object, Object[]) line: 45  
AbstractCallSite.call(Object, Object[]) line: 108   
AbstractCallSite.call(Object) line: 112 
GroovyMMTester$Map.configure() line: 18 <-- Person.getName() call is in here, but doesn't show
4

2 回答 2

1

我认为你遇到的问题基本上是你有调用方法的Java思维会直接调用该方法并完成它。好吧,甚至 Java 也没有这样做,但这些东西隐藏在 JVM 中。Groovy 没有修改 JVM 的奢侈,因此可能会在调用最终方法之前调用一组方法。由于这是一个实现细节,因此顺序可能会有所不同。由于 Groovy 是一种具有运行时元编程的语言,因此您期望的目标方法可能根本不会被调用。

无论如何,为了能够在 Groovy 中调用 getName() 方法,Groovy 运行时首先必须获取调用对象的元类,这会导致调用 getMetaClass()。如果您在此处拦截,那么您可能永远无法获得所需的方法调用。

解决方案实际上很简单……您只需过滤那些辅助方法。这将是任何以 $ 开头的方法和任何以 this$ 开头的方法,以及 super$ 和 getMetaClass 方法。过滤意味着在这里你不拦截,而只是使用反射继续调用。如果您遇到了一种不在该集合中的方法,那么您很可能拥有目标。在您的示例中,method.getName() 将返回“getName”。

于 2013-08-23T09:08:38.510 回答
0

请检查/共享您用于调用该方法的代码,就像有时在向它使用or方法getName()的 groovy 对象请求属性时一样,它们都调用该方法,我认为这是您实际发生的事情。getPropertygetAttributegetStaticMetaClass()

我的意思是,实际上不是直接调用getNameoaPerson对象,而是调用getProperty(..., personObject, 'name', ...)调用getStaticMetaClass().getProperty(..., personObject, 'name', ...).

您还可以尝试调试代码method.getName(),例如在您调用的行上放置一个断点,并查看堆栈跟踪是如何getName()调用该方法的。

于 2013-08-18T00:33:40.380 回答