如何在ByteBuddy中向类添加字段并在方法拦截器中设置/获取该值

时间:2016-01-29 15:06:13

标签: java bytecode byte-buddy

我使用byte-buddy在Ignite之上构建ORM,我们需要在类中添加一个字段,然后在方法拦截器中访问它。

所以这是我向一个类添加字段

的示例
class MyListener implements KeyListener{
    @Override
    public void keyPressed(KeyEvent e) {
        // Logic goes here
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // Logic goes here

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // Logic goes here
    }
}

拦截器就像这样

final ByteBuddy buddy = new ByteBuddy();

final Class<? extends TestDataEnh> clz =  buddy.subclass(TestDataEnh.class)
        .defineField("stringVal",String.class)
        .method(named("setFieldVal")).intercept(
            MethodDelegation.to(new SetterInterceptor())
    )
    .make()
    .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
    .getLoaded();

final TestDataEnh enh = clz.newInstance();

enh.getFieldVal();
enh.setFieldVal();

System.out.println(enh.getClass().getName());

那么如何将新字段的值放入拦截器中以便我可以更改它的值? (stringVal)

提前致谢

1 个答案:

答案 0 :(得分:1)

您可以使用FieldProxy按名称访问字段。您需要安装FieldProxy.Binder并在MethodDdelegation上注册才能使用它,因为它需要自定义类型才能进行类型安全的检测。 javadoc 解释了如何做到这一点。或者,您可以使用@This在实例上使用反射。 JVM在优化反射的使用方面非常有效。

一个例子是:

interface FieldGetter {
  Object getValue();
}

interface FieldSetter {
  void setValue(Object value);
}

public class SetterInterceptor {
  @RuntimeType
  public  Object intercept(@FieldProxy("stringVal") FieldGetter accessor) {
    Object value = accessor.getValue();
    System.out.println("Invoked method with: " + value);
    return value;
  }
}

对于bean属性,FieldProxy注释不需要显式名称,但会从截取的getter或setter的名称中发现名称。

安装可以按如下方式进行:

MethodDelegation.to(SetterInterceptor.class)
                .appendParameterBinder(FieldProxy.Binder.install(FieldGetter.class, 
                                                                 FieldSetter.class));