2

I'm trying to set up a class with Byte Buddy that implements all the interfaces of a given instance and forwards all calls to that instance, here's my code so far:

import static net.bytebuddy.implementation.Forwarding.to;

static Class<?> save (state) {
  return stream (state.getClass ().getMethods ())
    .filter (m -> isPublic (m.getModifiers ()))
    .reduce ((Builder<?>) new ByteBuddy ().subclass (Object.class)
      .implement (state.getClass ().getInterfaces ()),
             (b, m) -> {
               System.out.println ("Setting up method " + m.getName ());
               return b.define (new ForLoadedMethod (m))
                 .intercept (to (state));
              }, (x, y) -> {
                throw new UnsupportedOperationException ();
              }).make ().load (state.getClass ()
                .getClassLoader (), INJECTION).getLoaded ();
}

public static void main (String[] args) throws Throwable {
  System.out.println ("Saved: " + save (new Integer (1)).newInstance ().toString ());
}

This results in an exception like this:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot forward public boolean net.bytebuddy.renamed.java.lang.Object$ByteBuddy$rwGGy3NN.equals(java.lang.Object) to class java.lang.Integer
at net.bytebuddy.implementation.Forwarding$Appender.apply(Forwarding.java:337)
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)

I can see the note under Forwarding that for it to work the intercepted method must be defined on a super type of the given delegation target but I'm not sure what that means. If that means I should be subclassing the generated class, what if my target is of a final class? How else can I create a custom implementation that will forward these calls?

Also, since I'm here anyway, how can I specify a generic interface type to implement? Whether it's from a loaded java.lang.reflect.Type or from something I want to create on the fly?

4

1 回答 1

1

Forwarding 实现的工作方式类似于反射 API,其中目标需要是可分配的类型。由于您没有将 Integer 子类化(无论如何这是不可能的),因此转发委派失败。

我认为您正在寻找 MethodCall 委托,您可以在其中显式命名要调用的方法。那对你有用吗?

最后,实现泛型类型是 0.8 版计划的一个功能。我已经取得了不错的进展,并希望在 2016 年 1 月内准备好发布候选版本。我还计划重新访问转发委托,基于签名的调用应该不会太难实现。

于 2015-12-29T09:08:43.480 回答