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

问题描述 投票:2回答:1

我是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)方法假设objUser并调用它的getName(),然后另一个实现为getSurname()做同样的事情,等等。因此,等效的java代码将是:

public class MyHypotheticalByteBuddyExecutorImpl implements Executor {
    @Override
    Object execute(final Object target) {
        return ((User) target).getName();
    }
}

所以我的想法是能够为类+ 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();

...但是Byte Buddy正确地抛出一个异常,说我不能在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)方法的参数。

我该如何实现呢?

java code-generation introspection byte-buddy
1个回答
1
投票

这可以使用动态类型,您可以通过以下方式配置:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.