2013-08-16 13 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