如何将构造函数参数绑定到实例字段?
How can I bind constructor parameter to a instance field?
是否可以在 class 上创建新的最终字段并创建一个构造函数,其参数设置为 class 实例化时的最终字段?我尝试了几种方法并搜索了答案,但没有找到如何操作的示例。
我现在拥有的:
Class proxyClass = new ByteBuddy().subclass(Object.class).implement((Type[]) interfaces)
.defineField("dispatcherInvocationHandler", ByteBuddyDispatcherInvocationHandler.class, Modifier.PRIVATE + Modifier.FINAL)
.defineConstructor(Modifier.PUBLIC)
.withParameter(ByteBuddyDispatcherInvocationHandler.class)
.intercept(MethodCall.invokeSuper().andThen(/* copy argument to field */))
.method(ElementMatchers.any())
.intercept(InvocationHandlerAdapter.toField("dispatcherInvocationHandler"))
.make()
.load(BytebuddyProxyGenerator.class.getClassLoader())
.getLoaded();
我不想创建字段 public 并且我不想为该字段创建 属性 和 setter / getter。我想以这样的方式结束:
public class DontCare {
private final ByteBuddyDispatcherInvocationHandler dispatcherInvocationHandler;
public DontCare(ByteBuddyDispatcherInvocationHandler arg) {
super();
this.dispatcherInvocationHandler = arg;
}
}
有什么简单的方法可以做到这一点吗?
更新于 2016 年 10 月 31 日
在 Rafael 和 1.5.2 版本的 ByteBuddy 库的帮助下,我终于让它工作起来了。工作代码是这样的:
Class proxyClass = new ByteBuddy().subclass(Object.class).implement((Type[]) interfaces)
.defineField("dispatcherInvocationHandler", ByteBuddyDispatcherInvocationHandler.class, Modifier.PRIVATE + Modifier.FINAL)
.defineConstructor(Modifier.PUBLIC)
.withParameter(ByteBuddyDispatcherInvocationHandler.class)
.intercept(
MethodCall.invoke(Object.class.getConstructor())
.onSuper()
.andThen(
FieldAccessor.ofField("dispatcherInvocationHandler")
.setsArgumentAt(0)
)
)
.method(ElementMatchers.any())
.intercept(InvocationHandlerAdapter.toField("dispatcherInvocationHandler"))
.make()
.load(ByteBuddyProxyGenerator.class.getClassLoader())
.getLoaded();
可惜暂时没有好的办法。然而,我确实以此为灵感来重构 FieldAccessor
实现,它现在允许您执行以下操作:
builder.defineField("desiredField",
DispatcherInvocationHandler.class,
Visibility.PRIVATE, FieldManifestation.FINAL)
.defineConstructor(Visibility.PUBLIC)
.withParameters(String.class)
.intercept(MethodCall.invokeSuper() // Given such a constructor exists
.andThen(FieldAccessor.ofField("desiredField").setsArgumentAt(0)))
.make()
.load(BytebuddyProxyGenerator.class.getClassLoader())
.getLoaded();
当您定义这样一个明确的 setter 时,检测也可以自行链接。因此,您可以设置多个字段,例如:
FieldAccessor.ofField("foo")
.setsArgumentAt(0)
.andThen(FieldAccessor.ofField("bar").setsArgumentAt(1));
通过上述实现,构造函数(或任何方法)的实现类似于:
class Sample {
Object foo, bar;
Sample(Object a1, Object a2) {
foo = a1;
bar = a2;
}
}
此附加 API 随 Byte Buddy 1.5.2 一起发布。
是否可以在 class 上创建新的最终字段并创建一个构造函数,其参数设置为 class 实例化时的最终字段?我尝试了几种方法并搜索了答案,但没有找到如何操作的示例。
我现在拥有的:
Class proxyClass = new ByteBuddy().subclass(Object.class).implement((Type[]) interfaces)
.defineField("dispatcherInvocationHandler", ByteBuddyDispatcherInvocationHandler.class, Modifier.PRIVATE + Modifier.FINAL)
.defineConstructor(Modifier.PUBLIC)
.withParameter(ByteBuddyDispatcherInvocationHandler.class)
.intercept(MethodCall.invokeSuper().andThen(/* copy argument to field */))
.method(ElementMatchers.any())
.intercept(InvocationHandlerAdapter.toField("dispatcherInvocationHandler"))
.make()
.load(BytebuddyProxyGenerator.class.getClassLoader())
.getLoaded();
我不想创建字段 public 并且我不想为该字段创建 属性 和 setter / getter。我想以这样的方式结束:
public class DontCare {
private final ByteBuddyDispatcherInvocationHandler dispatcherInvocationHandler;
public DontCare(ByteBuddyDispatcherInvocationHandler arg) {
super();
this.dispatcherInvocationHandler = arg;
}
}
有什么简单的方法可以做到这一点吗?
更新于 2016 年 10 月 31 日
在 Rafael 和 1.5.2 版本的 ByteBuddy 库的帮助下,我终于让它工作起来了。工作代码是这样的:
Class proxyClass = new ByteBuddy().subclass(Object.class).implement((Type[]) interfaces)
.defineField("dispatcherInvocationHandler", ByteBuddyDispatcherInvocationHandler.class, Modifier.PRIVATE + Modifier.FINAL)
.defineConstructor(Modifier.PUBLIC)
.withParameter(ByteBuddyDispatcherInvocationHandler.class)
.intercept(
MethodCall.invoke(Object.class.getConstructor())
.onSuper()
.andThen(
FieldAccessor.ofField("dispatcherInvocationHandler")
.setsArgumentAt(0)
)
)
.method(ElementMatchers.any())
.intercept(InvocationHandlerAdapter.toField("dispatcherInvocationHandler"))
.make()
.load(ByteBuddyProxyGenerator.class.getClassLoader())
.getLoaded();
可惜暂时没有好的办法。然而,我确实以此为灵感来重构 FieldAccessor
实现,它现在允许您执行以下操作:
builder.defineField("desiredField",
DispatcherInvocationHandler.class,
Visibility.PRIVATE, FieldManifestation.FINAL)
.defineConstructor(Visibility.PUBLIC)
.withParameters(String.class)
.intercept(MethodCall.invokeSuper() // Given such a constructor exists
.andThen(FieldAccessor.ofField("desiredField").setsArgumentAt(0)))
.make()
.load(BytebuddyProxyGenerator.class.getClassLoader())
.getLoaded();
当您定义这样一个明确的 setter 时,检测也可以自行链接。因此,您可以设置多个字段,例如:
FieldAccessor.ofField("foo")
.setsArgumentAt(0)
.andThen(FieldAccessor.ofField("bar").setsArgumentAt(1));
通过上述实现,构造函数(或任何方法)的实现类似于:
class Sample {
Object foo, bar;
Sample(Object a1, Object a2) {
foo = a1;
bar = a2;
}
}
此附加 API 随 Byte Buddy 1.5.2 一起发布。