在ByteBuddy MethodDelegation中强制显式方法解析以允许使用lambdas

时间:2017-07-22 23:39:31

标签: java byte-buddy

我使用ByteBuddy在运行时实现标记接口和任意数量的类似访问器的无参数值方法,由标记注释标识,如:

interface Foo {
  // marker interface
}

// this is the kind of thing we're generating implementations of
interface MyFoo extends Foo {
  @Value
  SomeClass bar();
}

我有一个实现委托的功能接口,如:

interface Implementation<F extends Foo, V> {
  @RuntimeType
  V apply(@This F foo);
}

和生产实际实现的工厂。实现涉及各种泛型,通配符和未经检查(但已知是安全的)强制转换,这使得很难获得正确的类型参数。

interface ImplFactory<V> {
  boolean canImplement(Method m);
  <F extends Foo> Implementation<F, ?> implFor(Method m);
}

class Factories {
  static <F extends Foo> Implementation<F, ?> implFor(Method m) {
    ImplFactory<?> factory = factories.find((f) -> canImplement(m))
    return factory.implFor(m);
  }
}

Implementation<F, ?> impl = Factories.implFor(m);
builder.method(ElementMatchers.is(m)).intercept(MethodDelegation.to(impl));

如果我使用lambdas,ByteBuddy抱怨它无法找到任何匹配的方法:

class SomeFactory implements ImplFactory<?XYZ> {
  <F extends Foo> Implementation<F, ?XYZ> implFor(Method m) {
    return (f) -> /* ...lookup & runtime cast shenanigans... */
  }
} 

(对于?XYZ,了解参数化类型和通配符的某些组合。)

尽管Implementation.apply()使用@RuntimeType@This进行了注释,但这是正确的 - 可能是因为在运行时ByteBuddy无法告诉lambda是Implementation? - 即使我向lambda添加@This,也会持续存在:

class SomeFactory implements ImplFactory<?XYZ> {
  <F extends Foo> Implementation<F, ?XYZ> implFor(Method m) {
    // still doesn't work
    return (@This F f) -> /* ...shenanigans... */
  }
} 

但是,如果我将lambda扩展为抽象类并重新注释,它可以工作:

class SomeFactory implements ImplFactory<?XYZ> {
  <F extends Foo> Implementation<F, ?XYZ> implFor(Method m) {
      return new Implementation<F, ?XYZ>() {
          @Override
          @RuntimeType
          ?XYZ apply(@This F foo) {
              /* ...shenanigans... */
          }
      }
  }
} 

我真正想要做的就是告诉ByteBuddy&#34;只需委托给这个对象,然后委托给apply()方法 - 相信我,它有效!&#34;但似乎没有办法做到这一点。

如何强制ByteBuddy使用特定的实现方法而不是尝试进行智能查找?

1 个答案:

答案 0 :(得分:0)

方法覆盖在运行时并不存在。由于多种原因,方法,字段或接口上的注释不会被继承,而Byte Buddy不会扫描继承层次结构以完成工作。

我建议您为具有注释的检测使用委托类,并将实际目标作为参数来解决此问题。