我是Byte Buddy的新手,我正试图用它来创建对对象执行getter方法的接口实现。我的界面如下:
public interface Executor {
Object execute(final Object target);
}
想法是,如果我有一个类,例如:
public class User {
...
public String getName() { return this.name; }
public String getSurname() { return this.surname; }
}
我需要能够创建Executor
接口的一种实现,其中execute(obj)
方法假定obj
是User
并调用其getName()
,然后对getSurname()
等执行相同操作的另一个实现。因此,等效的Java代码为:
public class MyHypotheticalByteBuddyExecutorImpl implements Executor {
@Override
Object execute(final Object target) {
return ((User) target).getName();
}
}
因此,我们的想法是能够为class + getter的任何组合创建类似于上述的类,例如User
+ getName()
。
我(我想)知道如何让Byte Buddy创建几乎可以做到这一点的类:
final Method nameMethod = User.class.getMethod("getName", null);
final Class<?> myHypotheticalByteBuddyExecutorImpl =
new ByteBuddy()
.subclass(Object.class)
.implement(Executor.class)
.method(ElementMatchers.named("execute"))
.intercept(MethodCall.invoke(nameMethod).onArgument(0))
.make()
.load(ByteBuddyTest.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
...但是随后字节好友正确抛出了一个异常,表明我无法在getName()
上执行方法Object
。因此,我假设我缺少((User) target)
演员表:
Exception in thread "main" java.lang.IllegalStateException: Cannot invoke public java.lang.String com.example.User.getName() on class java.lang.Object
at net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter$Resolved.toStackManipulation(MethodCall.java:2527)
at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3541)
at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3502)
...
我相信可以将其定义为StackManipulation
(我可能完全错了),例如:
final StackManipulation typeCasting =
TypeCasting.to(TypeDescription.ForLoadedType.of(User.class));
但是我无法在Byte Buddy API的任何地方找到如何在执行getter之前将这种强制转换(或可能需要强制转换的任何其他代码)应用于execute(Object)
方法的参数的方法。
我该如何实现?
答案 0 :(得分:1)
这应该通过使用动态类型来实现,您可以通过以下方式进行配置:
MethodCall.invoke(nameMethod)
.onArgument(0)
.withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC);
堆栈操作用于创建自定义字节码,我不认为这是您要在此处执行的操作。