java - 从 Java 检查 CGLib 代理的 Groovy 类

标签 java reflection groovy proxy-classes cglib

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

class Person {
  String name
}

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

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

最佳答案

我认为您遇到的问题基本上是您认为调用方法的 Java 会直接调用该方法并完成它。好吧,即使是 Java 也不会这样做,但这些东西隐藏在 JVM 中。 Groovy 没有修改 JVM 的奢侈,因此在调用 final方法之前可能会调用一组方法。由于这是一个实现细节,因此顺序可能会有所不同。由于 Groovy 是一种具有运行时元编程的语言,您期望的目标方法可能根本不会被调用。

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

解决方案其实很简单……您只需过滤那些辅助方法即可。那将是任何以 $ 开头的方法和任何以 this$ 开头的方法,以及 super$ 和 getMetaClass 方法。过滤意味着你不拦截,而只是通过反射继续调用。如果你遇到了一种不在那个集合中的方法,那么你很可能有目标。在您的示例中,method.getName() 将返回“getName”。

关于java - 从 Java 检查 CGLib 代理的 Groovy 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18283157/

相关文章:

java - 在 Java 中查找简单序列重复的有效方法

java - 套接字 ObjectOutpuStream ObjectInputStream

c++ - 对象反射

jenkins - build.gradle 中的警告

java - Groovy getter/setter 速记符号和 API 更改

java - 从接受的扫描仪读取参数

java - Reflection Method.getParameterTypes() - 对象参数数组

c# - 有初始化的设计模式吗? C#

grails - Grails:1.3.7中的异步服务

java - JPA - 实体未持久化