【问题标题】:Invoke method on a argument with a cast using Byte Buddy使用 Byte Buddy 对带有强制转换的参数调用方法
【发布时间】:2019-08-26 01:40:00
【问题描述】:

我对 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 正确地抛出了一个异常,说我无法在 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) 方法的参数。

我该如何实现?

【问题讨论】:

    标签: java code-generation introspection byte-buddy


    【解决方案1】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-11
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 2017-10-23
      • 2015-09-23
      • 1970-01-01
      相关资源
      最近更新 更多