【发布时间】:2017-07-31 04:47:11
【问题描述】:
我正在使用 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 “只需委托给这个对象,然后委托给 apply() 方法——相信我,它有效!”但似乎没有任何方法可以做到这一点。
如何强制 ByteBuddy 使用特定的实现方法而不是尝试进行智能查找?
【问题讨论】:
标签: java byte-buddy