通过 reflection/javassist 调用不存在的函数
Calling a function that does not exist via reflection/javassist
我需要调用一个函数 - (属性 的 getter 和 setter),但我的问题是,属性 的名称是在运行时生成的(某些变量的名称 + 数字).
是否可以通过 javassist 或 gclib 操纵字节码,以便将函数调用定向到某个代理 object/function,并从被调用的函数名中提取真实的方法名称和编号,以便我可以在之后调用函数(以数字作为参数)?
我尝试了以下方法,但没有用:
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) {
String realMethodName=thisMethod.substring(0,5);
Integer param=Integer.parseInt(thisMethod.substring(5));
Method m = self.getClass().getMethod(realMethodName);
m.invoke(self,param);
return null;
}
};
我认为这可能是使用 Java 反射代理对象可能派上用场的少数场景之一。
您可以定义一些接口,但将方法委托给(动态)调用处理程序,后者将调用那些 "getter/setter" 方法。
旁注:在实现这样的调用处理程序时,您必须了解对相应对象的任何方法调用都会触发其 "invoke" 方法;当您调用 toString 或 equals 或从 Object 继承的任何其他内容时发生的事件。
编辑:还有一个(不同的)想法:你确定你需要创建动态方法名吗?如果您有一些数字(或基于字符串)键 - 例如不使用 Map 怎么办?
喜欢
Map<WhateverKeyType,YourPropertyClass>
那会是 "normal java" 处理问题的更多方式(而不是考虑反射或字节码操作)。
如果您想实现类似的东西但可以考虑使用除 javassist 之外的其他库,请考虑 using Byte Buddy(我写的,以供披露)。
考虑到,你有一个接口
interface Foo { Object getProperty() }
您想实施以访问 bean属性 的
class Bar { Object getAbc123() { ... } }
然后使用 Byte Buddy,您可以实现 class
Foo accessor = new ByteBuddy()
.subclass(Foo.class)
.method(named("getProperty"))
.intercept(MethodCall.invoke(Bar.class.getDeclaredMethod("getAbc123"))
.on(new Bar()))
.make()
.load(Foo.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.newInstance();
将 getProperty
的调用重定向到您选择的方法的接口。通过一些自定义,您一定可以创建更通用的解决方案。
我需要调用一个函数 - (属性 的 getter 和 setter),但我的问题是,属性 的名称是在运行时生成的(某些变量的名称 + 数字).
是否可以通过 javassist 或 gclib 操纵字节码,以便将函数调用定向到某个代理 object/function,并从被调用的函数名中提取真实的方法名称和编号,以便我可以在之后调用函数(以数字作为参数)?
我尝试了以下方法,但没有用:
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) {
String realMethodName=thisMethod.substring(0,5);
Integer param=Integer.parseInt(thisMethod.substring(5));
Method m = self.getClass().getMethod(realMethodName);
m.invoke(self,param);
return null;
}
};
我认为这可能是使用 Java 反射代理对象可能派上用场的少数场景之一。
您可以定义一些接口,但将方法委托给(动态)调用处理程序,后者将调用那些 "getter/setter" 方法。
旁注:在实现这样的调用处理程序时,您必须了解对相应对象的任何方法调用都会触发其 "invoke" 方法;当您调用 toString 或 equals 或从 Object 继承的任何其他内容时发生的事件。
编辑:还有一个(不同的)想法:你确定你需要创建动态方法名吗?如果您有一些数字(或基于字符串)键 - 例如不使用 Map 怎么办?
喜欢
Map<WhateverKeyType,YourPropertyClass>
那会是 "normal java" 处理问题的更多方式(而不是考虑反射或字节码操作)。
如果您想实现类似的东西但可以考虑使用除 javassist 之外的其他库,请考虑 using Byte Buddy(我写的,以供披露)。
考虑到,你有一个接口
interface Foo { Object getProperty() }
您想实施以访问 bean属性 的
class Bar { Object getAbc123() { ... } }
然后使用 Byte Buddy,您可以实现 class
Foo accessor = new ByteBuddy()
.subclass(Foo.class)
.method(named("getProperty"))
.intercept(MethodCall.invoke(Bar.class.getDeclaredMethod("getAbc123"))
.on(new Bar()))
.make()
.load(Foo.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.newInstance();
将 getProperty
的调用重定向到您选择的方法的接口。通过一些自定义,您一定可以创建更通用的解决方案。