3

メソッドの戻り値とパラメーターの型が何であるかを知るために、Java から、いくつかの CGLib プロキシされた Groovy クラスで Groovy によって生成されたメソッドを調べようとしています。例として、次の Groovy クラスを検討してください。

class Person {
  String name
}

Groovyは name プロパティのメソッドを生成getName()します。おそらく aを返し、おそらく a を取ります。setName()getName()StringsetName()String

しかし、CGLib を介してこのクラスをプロキシし、getNameCGLib の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 メソッドです。ここでのフィルタリングとは、傍受するのではなく、Reflection を使用して呼び出しを継続することを意味します。そのセットにない 1 つのメソッドに出会った場合は、おそらくターゲットを持っています。あなたの例では、method.getName() は「getName」を返します。

于 2013-08-23T09:08:38.510 に答える
0

メソッドを呼び出すために使用するコードを確認/共有してください。またはメソッドgetName()を使用するグルーヴィーなオブジェクトにプロパティを要求するときに、両方がメソッドを呼び出すことがあります。これは実際に起こっていることだと思います。getPropertygetAttributegetStaticMetaClass()

つまり、オブジェクトを直接呼び出すのではなく、getName実際Personには を呼び出すメソッドgetProperty(..., personObject, 'name', ...)を呼び出しているということgetStaticMetaClass().getProperty(..., personObject, 'name', ...)です。

method.getName()たとえば、呼び出す行にブレークポイントを置いてコードをデバッグし、スタックトレースでgetName()メソッドがどのように呼び出されているかを確認することもできます。

于 2013-08-18T00:33:40.380 に答える