Byte Buddy 的方法委托

Method delegation with Byte Buddy

我在获取使用 Byte Buddy 的简单示例时遇到问题,这是我的代码:

import static java.util.Arrays.asList;
import java.util.stream.Stream;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;

public class Foo {
  public static class Bar {
    public void bar (String s, Integer i) {
      System.out.println ("s:" + s + " i:" + i);
    }
  }
  public static class Baz {
    public void baz (Integer i, String s) {
      System.out.println ("i:" + i + " s:" + s);
    }
  }

  public static void main (String[] args) {
    try {
      Class<?> c = new ByteBuddy ()
        .subclass (Object.class)
        .defineMethod ("bar", Void.class, asList (String.class, Integer.class), 1)
        .intercept (MethodDelegation.to (new Bar ()))
        .defineMethod ("baz", Void.class, asList (Integer.class, String.class), 1)
        .intercept (MethodDelegation.to (new Baz ()))
        .make ()
        .load (Foo.class.getClassLoader (), ClassLoadingStrategy.Default.WRAPPER)
        .getLoaded ();
      Stream.of (c.getDeclaredMethods ()).forEach (System.out::println);
    } catch (Exception e) {
      e.printStackTrace ();
    }
  }
}

我希望将调用转发给相关的拦截器实例,但是我得到了这个异常:

java.lang.IllegalArgumentException: None of [protected void java.lang.Object.finalize() throws java.lang.Throwable, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException, public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll(), public void Foo$Bar.bar(java.lang.String,java.lang.Integer)] allows for delegation from public java.lang.Void net.bytebuddy.renamed.java.lang.Object$ByteBuddy$P87HQ3lQ.bar(java.lang.String,java.lang.Integer)
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 Foo.main(Foo.java:55)

最奇怪的部分是在该异常消息的最后:

[...] public void Foo$Bar.bar(java.lang.String,java.lang.Integer)] allows for delegation from public java.lang.Void net.bytebuddy.renamed.java.lang.Object$ByteBuddy$P87HQ3lQ.bar(java.lang.String,java.lang.Integer)

我做错了什么?

当我提交并回顾我的问题时,我认为问题可能出在 void return 而不是 Void 并且果然,改变 return 在拦截器上键入工作

你的假设是对的。字节好友无法将 void non-type 分配给 Void 类型。但是,当您使用 @RuntimeType:

注释拦截器时,Byte Buddy 可以将 null 分配给 void 方法的引用类型
public class Bar {
  @RuntimeType
  public void bar (String s, Integer i) {
    System.out.println ("s:" + s + " i:" + i);
  }
}
public class Baz {
  @RuntimeType
  public void baz (Integer i, String s) {
    System.out.println ("i:" + i + " s:" + s);
  }
}