我使用 Byte Buddy (v0.5.2) 动态创建接口的“子类”(实际上,我想创建一个实现该接口的类)。在此类的实例上调用的所有方法都应重定向到另一个(拦截器)类。我使用了以下代码(“TestInterface”是一个接口,它声明了一个方法“sayHello”):
final Interceptor interceptor = new Interceptor();
Class<?> clazz = new ByteBuddy()
.subclass(TestInterface.class)
.method(any()).intercept(MethodDelegation.to(interceptor))
.make()
.load(TestInterface.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
TestInterface instance = (TestInterface) clazz.newInstance();
instance.sayHello();
拦截器类如下所示:
public class Interceptor {
public Object intercept(@Origin MethodHandle method, @AllArguments Object[] args) throws Throwable {
...
}
}
但是,当我尝试调用“sayHello”方法(我的代码示例的最后一行)时,我得到一个“IncompatibleClassChangeError”。堆栈跟踪如下:
Exception in thread "main" java.lang.IllegalAccessError: no such method: byteuddytest.TestInterface.sayHello()void/invokeVirtual
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:448)
at bytebuddytest.TestInterface$ByteBuddy$0E9xusGs.sayHello(Unknown Source)
at bytebuddytest.Main.main(Main.java:32)
Caused by: java.lang.IncompatibleClassChangeError: Found interface bytebuddytest.TestInterface, but class was expected
at java.lang.invoke.MethodHandleNatives.resolve(Native Method)
at java.lang.invoke.MemberName$Factory.resolve(MemberName.java:965)
at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:990)
at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1387)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1732)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:442)
... 2 more
该问题似乎与我的拦截器方法中使用“MethodHandle”参数有关。当我将类型更改为“方法”时,一切正常。但是根据文档,由于性能原因,应该首选“MethodHandle”而不是“Method”。
错误是由 Byte Buddy 中的错误引起的,还是在这种情况下我实际上应该使用“方法”参数?