使用 Byte Buddy 的简单前后方法拦截器

Simple After And Before Method Interceptor With Byte Buddy

在撰写本文时,在 Byte Buddy tutorial 中,一切都得到了解释,但没有简单的前后方法拦截器,正如我在下面解释的那样,我是不是遗漏了什么,或者教程很复杂。 (参见 LoggerInterceptor 示例给出了方法但没有对象,ChangingLoggerInterceptor 示例给出了对象但没有调用方法)

我想要实现的是在 setter 方法执行后调用对象的方法。如何编写拦截器并在 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

即使没有方法委托,您也可以实现这样的机制,如下所示:

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

这样,每个 setter 都被覆盖以首先调用其超级方法,然后以 true 作为参数调用 setDirty 方法。然而,评论中的链接示例也应该有效。

拦截器可能如下所示(假定已实现某些接口 Dirtiable):

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

这假设检测的超级 class 实现了 Dirtiable 接口,这可以使用 .implement(Dirtiable.class) 完成,其中可以使用 [=17= 实现该方法来设置字段] 实施。