2013-08-16 48 views
3

我想检查一些CGLib代理Groovy类,从Java,Groovy生成的方法,以了解什么是返回和参数类型的方法。当然,考虑这个Groovy类:检查来自Java的CGLib代理Groovy类

class Person { 
    String name 
} 

Groovy产生的getName()setName()方法的name属性。 getName()据推测返回StringsetName()大概需要String

但通过使用CGLIB这个类和使用CGLIB的MethodInterceptormethod.getName()回报getMetaClassmethod.getReturnType()回报groovy.lang.MetaClass拦截针对getName调用时。

有没有办法从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 
+0

什么原因使用CGLib而不是[Metaclass](http://groovy.codehaus.org/Evaluating+the+MetaClass+runtime)? – ChrLipp

+0

我想你所调用的是Person对象上的getName(),而不是直接Person.getName()。对? – Alfergon

回答

1

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

无论如何,为了能够在Groovy中调用方法getName(),Groovy运行时首先必须获取调用的对象的元类,这会导致对getMetaClass()的调用。如果你在这里拦截,那么你可能永远不会达到你想要的那种方法。

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

+0

工程很棒。谢谢! – Jonathan

0

请检查/分享您使用调用getName()方法,有时代码要求的属性,当一个时髦的对象它使用getPropertygetAttribute方法,他们都称为getStaticMetaClass()方法,我认为这是实际发生在你身上的事情。

我的意思是,而不是直接调用getName o一个Person对象它实际上callling它调用getStaticMetaClass().getProperty(..., personObject, 'name', ...)方法getProperty(..., personObject, 'name', ...)

你也可以尝试调试你的代码,把一个断点放在你叫method.getName()的那一行上,然后看看堆栈跟踪如何调用getName()方法。

+0

OP想要在Java中使用反射来了解返回类型。:) – dmahapatro

+0

我正在使用CGLib代理类,和CGLib的[MethodInterceptor](http://cglib.sourceforge.net/apidocs/net/sf/cglib/proxy/MethodInterceptor.html)拦截调用getName/setName 。这是我想从中学习“财产类型”的出发点。不幸的是,似乎没有办法从拦截器中学习什么方法的名称,因为'method.getName()'返回'$ getStaticMetaClass'。 – Jonathan

+0

你可以添加代码的调用部分? – Alfergon