Java Bytecode: custom setter / getter with byte buddy

I am trying to create a "custom" setter method for a byte buddy field. Buddy's own mechanism makes it very easy to implement the standard setter / getter methods, however, I'm looking for an elegant way to extend the setter with some additional logic.

To simplify the example, suppose we have a class A that has a setChanged (String) method. The goal is to subclass Class A, add a field with the appropriate access methods. The trick is that I want to call setChanged ("fieldName") from each setter method added.

public void setName(String name)
{
  setChanged("name");
  this.name = name;
}

For the “normal” setter method, the byte implementation of byddy would be:

new ByteBuddy()
  .subclass(A.class)
  .name("B")
  .defineField("name", Integer.TYPE, Visibility.PUBLIC)
   // args is a ArrayList<Class<?>>
  .defineMethod(getSetterName(name), Void.TYPE, args, Visibility.PUBLIC) 
  .intercept( FieldAccessor.ofField(name) )

Bytecode I look like this:

L0
 ALOAD 0       // Loads the this reference onto the operand stack
 ILOAD 1       // Loads the integer value of the local variable 1 (first method arg)
 PUTFIELD package/B.name : I // stores the value to the field
L1
 ALOAD 0
 LDC "name"
 INVOKEVIRTUAL package/A.setChanged (Ljava/lang/String;)V
 RETURN

: FieldAccessor ?

+4
1

Instrumentation . , Instrumentation.Compound , , FieldAccessor.ofBeanProperty() , , .

, Byte Buddy :

  • Instrumentation: . , , . , , .
  • A ByteCodeAppender Instrumentation , , .
  • A StackManipulation - . .

, ( this) . :

  • this MethodVariableAccess.REFERENCE.loadFromIndex(0).
  • , , . , ByteCodeAppender . TextConstant, .
  • MethodInvocation, setChanged TypeDescription, Instrumentation.

, , Byte Buddy API - DSL Java. , Byte Buddy 0.4, , . , Byte Buddy, MethodDelegation. , Java .

, beans :

interface Changeable {
  void setChanged(String field);
}

, :

class Interceptor {
  static void intercept(@This Changeable thiz, @Origin Method method) {
    thiz.setChanged(method.getName());
  }
}

, Byte Buddy . , . this , .

, - . , Byte Buddy 0.4, Instrumentation :

MethodDelegation.to(Interceptor.class).andThen(FieldAccessor.ofBeanProperty())

Byte Buddy intercepor ( ) , , Instrumentation, andThen.

+3

All Articles