繁体   English   中英

从Java检查CGLib代理的Groovy类

[英]Inspect CGLib proxied Groovy classes from Java

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

class Person {
  String name
}

Groovy为name属性生成getName()setName()方法。 getName()可能会返回一个StringsetName()可能会返回一个String

但是当通过CGLib代理此类并使用CGLib的MethodInterceptor拦截对getName调用时,method.getName method.getName()返回getMetaClassgetMetaClass 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

我认为你遇到的问题基本上就是你有Java思考调用方法会直接调用方法并完成它。 好吧,甚至Java都没有,但这些东西都隐藏在JVM中。 Groovy并不擅长修改JVM,因此在调用final方法之前可能会调用一组方法。 由于这是一个实现细节,序列可能会有所不同。 由于Groovy是一种运行时元编程的语言,因此您可能根本不会调用目标方法。

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

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

请检查/共享用于调用getName()方法的代码,因为有时在向groovy对象请求属性时它使用getPropertygetAttribute方法,并且它们都调用getStaticMetaClass()方法,我认为这是什么实际上正在发生在你身上。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM