我正在尝试从Java中检查一些CGLib代理的Groovy类上的Groovy生成的方法,以了解方法的返回和参数类型。例如,考虑一下这个Groovy类:
class Person {
String name
}
Groovy为name属性生成getName()
和setName()
方法。 getName()
可能会返回String
,而setName()
可能需要String
。
但是当通过CGLib代理此类并使用CGLib的MethodInterceptor拦截对getName
的调用时,method.getName()
返回getMetaClass
并且method.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
答案 0 :(得分:1)
我认为你遇到的问题基本上就是你有Java思考调用方法会直接调用方法并完成它。好吧,甚至Java都没有,但这些东西都隐藏在JVM中。 Groovy并不擅长修改JVM,因此在调用final方法之前可能会调用一组方法。由于这是一个实现细节,序列可能会有所不同。由于Groovy是一种运行时元编程的语言,因此您可能根本不会调用目标方法。
无论如何,为了能够在Groovy中调用方法getName(),Groovy运行时首先必须获取调用Object的元类,这将导致调用getMetaClass()。如果你在这里拦截,那么你可能永远不会得到你想要的方法调用。
解决方案实际上很简单......你只需要过滤那些辅助方法。这将是以$开头的任何方法以及以此$开头的任何方法,以及super $和getMetaClass方法。过滤意味着您不会拦截,而只需使用Reflection继续调用。如果您遇到一个不在该集合中的方法,那么您很可能拥有目标。在你的例子中,method.getName()将返回“getName”。
答案 1 :(得分:0)
请检查/分享用于调用getName()
方法的代码,因为有时在向Groovy对象请求属性时,它使用getProperty
或getAttribute
方法,并且他们调用getStaticMetaClass()
方法,我认为这是实际发生在你身上的方法。
我的意思是,不是直接调用getName
o Person
对象,而是实际调用调用getProperty(..., personObject, 'name', ...)
的方法getStaticMetaClass().getProperty(..., personObject, 'name', ...)
。
您也可以尝试调试代码,例如在您调用method.getName()
的行上放置一个断点,然后查看堆栈跟踪如何调用getName()
方法。