How to add a field to a class in ByteBuddy and set / get that value in a method interceptor

*爱你&永不变心* 提交于 2019-12-10 20:51:17

问题


I am using byte-buddy to build an ORM on top of Ignite, we need to add a field to a class and then access it in a method interceptor..

So here's an example where I add a field to a class

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());

And the Interceptor is like this

public class SetterInterceptor {
    @RuntimeType
    public  Object intercept() {
        System.out.println("Invoked method with: ");
        return null;
    }
}

So how do I get the value of the new field into the interceptor so I can change it's value? (stringVal)

Thanks in advance


回答1:


You can use a FieldProxy to access a field by its name. You need to install a FieldProxy.Binder and register it on the MethodDdelegation before you can use it as it requires a custom type for type-safe instrumentation. The javadoc explains how this can be done. Alternatively, you can use reflection on an instance by using @This. The JVM is quite efficient in optimizing the use of reflection.

An example would be:

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;
  }
}

For bean properties, the FieldProxy annotation does not require an explicit name but discovers the name from the name of the intercepted getter or setter.

The installation can be done as follows:

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


来源:https://stackoverflow.com/questions/35087647/how-to-add-a-field-to-a-class-in-bytebuddy-and-set-get-that-value-in-a-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!