Juan Zhong
Juan Zhong

Reputation: 179

How to generate proxy with custom field using cglib?

I'm using cglib to generate proxy object of some class, and I need to bind some custome fields to the proxy object like shown below

    String customFieldName = "myCustomField";
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(targetClass);
    // What can I do to add custom field to the proxy class ?

    enhancer.setCallback(new MethodInterceptor() {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            // I'd access the custom field value here
            Field field = obj.getClass().getField(customFieldName);
            Object customFieldValue = field.get(obj);

            // do something

            return proxy.invokeSuper(obj, args);
        }
    });

Of course an alternative is using a map to bind the value to the origin object but I don't really like to do this.

Has anyone got any idea ?

Upvotes: 1

Views: 1041

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 44042

This is not possible when using cglib, there is no API for it unless you are willing to access the underlying ASM API to add the field directly in byte code. If you are willing to change tool, you can however use Byte Buddy, a library that I maintain:

Class<? extends TargetClass> proxy = new ByteBuddy()
  .subclass(targetClass)
  .method(any())
  .intercept(MethodDelegation.to(MyInterceptor.class)
                             .andThen(SuperMethodCall.INSTANCE)
  .defineField("myCustomField", Object.class, Visibility.PUBLIC)
  .make()
  .load(targetClass.getClassLoader())
  .getLoaded();

class MyInterceptor {
  static void intercept(@FieldValue("myCustomField") Object myCustomField) {
    // do something
  }
}

With cglib, you could alternatively add a callback to delegate to a specific enhancer instance for each individual proxy by using callback class.

Upvotes: 2

Related Questions