在Byte Buddy中设置instanceField

时间:2016-07-01 16:53:30

标签: java bytecode instrumentation byte-buddy

我正在试图弄清楚如何使用Byte Buddy设置实例字段的值。文档说:

  

在调用此类动态类的实例上的方法之前,请务必记住为此字段指定值。否则,方法委派将导致NullPointerException。

但我没有在文档或单元测试中看到如何执行此操作。

我的动态课程是:

new ByteBuddy().subclass(AbstractService.class)
        .name(serviceName)
        .method(ElementMatchers.named("start").and(
                ElementMatchers.takesArguments(0)))
        .intercept(
                MethodDelegation.toInstanceField(service, "consumer")
                    .filter(ElementMatchers.isAnnotatedWith(Start.class)))
        .method(ElementMatchers.named("stop").and(
                ElementMatchers.takesArguments(0)))
        .intercept(
                MethodDelegation.to(instance).filter(
                        ElementMatchers.isAnnotatedWith(Stop.class)))
        .make();

我看到另一篇帖子的答案是拦截任何构造函数,并使用@FieldProxyMethodDelegation,但我不明白该怎么做。我在.constructor(ElementMatchers.any()).intercept(...)的某些变体的结果方面尝试过的所有内容都会导致:

  

java.lang.IllegalArgumentException:[]不允许来自...的委派

1 个答案:

答案 0 :(得分:0)

基本上,当您使用MethodDelegation.toInstanceField时,Byte Buddy会在生成的类中添加给定名称的字段。在您的情况下,Byte Buddy添加了一个名为service的{​​{1}}字段。

现在,您需要决定如何为此字段指定值,因为该字段没有值,即在分配之前为"consumer"。如果在执行此操作之前调用了使用null注释的方法,则会遇到@Start

分配字段的最简单方法是反射。类型安全的替代方案是实现一些接口

NullPointerException

鉴于您的interface SetterIFace { void setConsumer(MyType myType); } 类型为service。然后,您可以添加:

Class<MyType>

.implement(SetterIFace.class).intercept(FieldAccessor.ofBeanProperty()) 中定义后,将SetterIFace实施为相关字段的设置者。