【问题标题】:Set an instanceField in Byte Buddy在 Byte Buddy 中设置 instanceField
【发布时间】:2016-07-01 16:53:29
【问题描述】:

我正在尝试弄清楚如何使用 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: [] 中的任何一个都不允许...

【问题讨论】:

    标签: java bytecode instrumentation byte-buddy


    【解决方案1】:

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

    您现在需要决定如何为该字段分配值,因为该字段没有值,即在分配之前是null。如果在调用之前调用了带有@Start 注释的方法,则会遇到NullPointerException

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

    interface SetterIFace {
      void setConsumer(MyType myType);
    }
    

    假设您的 service 类型是 Class<MyType>。然后你可以添加:

    .implement(SetterIFace.class).intercept(FieldAccessor.ofBeanProperty())
    

    MethodDelegation 中定义后,将SetterIFace 实现为相关字段的设置器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多