Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple After And Before Method Interceptor With Byte Buddy

In Byte Buddy tutorial at the time of this writing, everything is explained but a simple after and before method interceptor is not there as I explained below, am I missing something or tutorial is complex. (See LoggerInterceptor example gives method but not object, ChangingLoggerInterceptor example gives object but not invoked method)

What I wanted to achieve is to call a method of an object after its setter method executions. How can I write an interceptor and use it in Java 6?

public class DirtyClass{

private String _sField;
private boolean _bDirty;

public void setField(String sField) {
    _sField = sField;
    //setDirty(true); to be appended after proxying
}
public String getField() {
    return _sField;
}
public void setDirty(boolean bDirty){
    _bDirty = bDirty;
}
public boolean isDirty(){
    return _bDirty;
}
}

DirtyClass d = new ByteBuddy().subclass(DirtyClass.class)...???

d.setField("dirty now");
System.out.println(d.isDirty()); //Expecting true
like image 296
John Smith Avatar asked Dec 14 '22 00:12

John Smith


1 Answers

You can implement such a mechanism even without a method delegation as follows:

DirtyClass d = new ByteBuddy()
  .subclass(DirtyClass.class)
  .method(isSetter().and(not(named("setDirty"))))
  .intercept(SuperMethodCall.INSTANCE.andThen(
      MethodCall.invoke(DirtyClass.class.getMethod("setDirty", boolean.class))
                .with(true)
  )).make()
  .load(DirtyClass.class.getClassLoader())
  .getLoaded()
  .newInstance();

This way, every setter is overridden to first invoke its super method and then to invoke the setDirty method with true as an argument. The linked example in the comments should however work as well.

An interceptor could look like the following (given that some interface Dirtiable is implemented):

public class Interceptor {
  public static void getter(@SuperCall Runnable zuper, @This Dirtiable self) {
    zuper.run();
    self.setDirty(true);
  }
}

This assumes that the instrumented super class implements the Dirtiable interface which can be done using .implement(Dirtiable.class) where the method can be implemented to set a field using the FieldAccessor implementation.

like image 119
Rafael Winterhalter Avatar answered Jan 23 '23 03:01

Rafael Winterhalter