使用 Byte Buddy 对具有强制转换的参数调用方法



我对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();
}
}

所以这个想法是能够为类 + getter 的任意组合创建像上面这样的类,就像在这种情况下一样User+getName().

我(我想我)知道如何让字节好友创建一个几乎可以做到这一点的类:

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();

。但随后字节好友正确地抛出了一个异常,说我无法在Object上执行方法getName().因此,我假设我缺少((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)方法的参数。

我该如何实现?

这应该通过使用动态类型来工作,您可以通过以下方式配置:

MethodCall.invoke(nameMethod)
.onArgument(0)
.withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC);

堆栈操作用于创建自定义字节代码,我认为这不是您在这里要做的。

最新更新