如何使用 Byte-Buddy 从接口构建 Java Class 的具体实现?
How do I build an concrete implementation of a Java Class from an interface using Byte-Buddy?
我有一个界面,假设它看起来像这样。
public interface TestObject {
String getString();
Long getLong();
}
我想使用 ByteBuddy 实际构建此对象的具体实现。
这是我试过的。
public class Runme {
public static void main(String[] args) {
ByteBuddy bb = new ByteBuddy();
Class<?> clz = bb
.subclass(TestObject.class)
.method(any()).intercept(MethodDelegation.to(Interceptor.class))
.make()
.load(Object.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
try {
Object test = clz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public class Interceptor {
public Object intercept(@Origin String method, @AllArguments Object[] args) throws Throwable {
System.out.println("I have intercepted a call");
return "Hello";
}
}
}
我收到这个错误
Exception in thread "main" java.lang.IllegalArgumentException: None of [] allows for delegation from public boolean java.lang.Object.equals(java.lang.Object)
at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.process(MethodDelegationBinder.java:881)
at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1218)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:510)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:444)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:3193)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1481)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:234)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$AbstractDelegatingBuilder.make(DynamicType.java:2177)
at com.meta.testbytebuddy.Runme.main(Runme.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
我做错了什么++..如果我想实现多个接口怎么办?
我正在使用 ByteBuddy 来生成代码。
问题是您通过 MethodDelegation.to(Interceptor.class)
委托给拦截器的静态方法,而拦截器 class 只声明了 non-static 成员。您可以将拦截器方法声明为 static
,也可以委托给一个实例而不是 class。我觉得前一种方式更合适
然而,仅此一项仍然行不通。您正在从拦截器 returning 一个 Object
类型,同时您正在拦截 any()
方法。这包括 TestObject
接口的方法,也包括 Object
声明的方法,即隐式超级 class。您可以按如下方式定义您的拦截器以使您的 class 编译,然后 Byte Buddy 会将 return 类型转换为每个方法的 return 类型,这将导致 ClassCastException
:
public class Interceptor {
@RuntimeType
public static Object intercept(@Origin String method, @AllArguments Object[] args) {
System.out.println("I have intercepted a call");
return "Hello";
}
}
我有一个界面,假设它看起来像这样。
public interface TestObject {
String getString();
Long getLong();
}
我想使用 ByteBuddy 实际构建此对象的具体实现。
这是我试过的。
public class Runme {
public static void main(String[] args) {
ByteBuddy bb = new ByteBuddy();
Class<?> clz = bb
.subclass(TestObject.class)
.method(any()).intercept(MethodDelegation.to(Interceptor.class))
.make()
.load(Object.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
try {
Object test = clz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public class Interceptor {
public Object intercept(@Origin String method, @AllArguments Object[] args) throws Throwable {
System.out.println("I have intercepted a call");
return "Hello";
}
}
}
我收到这个错误
Exception in thread "main" java.lang.IllegalArgumentException: None of [] allows for delegation from public boolean java.lang.Object.equals(java.lang.Object)
at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.process(MethodDelegationBinder.java:881)
at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1218)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:510)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:444)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:3193)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1481)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:234)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$AbstractDelegatingBuilder.make(DynamicType.java:2177)
at com.meta.testbytebuddy.Runme.main(Runme.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
我做错了什么++..如果我想实现多个接口怎么办?
我正在使用 ByteBuddy 来生成代码。
问题是您通过 MethodDelegation.to(Interceptor.class)
委托给拦截器的静态方法,而拦截器 class 只声明了 non-static 成员。您可以将拦截器方法声明为 static
,也可以委托给一个实例而不是 class。我觉得前一种方式更合适
然而,仅此一项仍然行不通。您正在从拦截器 returning 一个 Object
类型,同时您正在拦截 any()
方法。这包括 TestObject
接口的方法,也包括 Object
声明的方法,即隐式超级 class。您可以按如下方式定义您的拦截器以使您的 class 编译,然后 Byte Buddy 会将 return 类型转换为每个方法的 return 类型,这将导致 ClassCastException
:
public class Interceptor {
@RuntimeType
public static Object intercept(@Origin String method, @AllArguments Object[] args) {
System.out.println("I have intercepted a call");
return "Hello";
}
}