Byte-Buddy:方法拦截 InvoiceHandler 与 MethodDelegation 到 GeneralInterceptor

Fly*_*eep 5 java byte-buddy

我使用 Byte-Buddy 动态生成 Java 接口方法的实现,并将对这些方法的调用委托给现有代理对象的单个方法。

第一个版本的灵感来自如何使用 ByteBuddy 创建动态代理

它使用反射InvocationHandler

即具体代理类:

  • 实现接口InvocationHandler
  • 覆盖该方法invoke()

这很好用。

然后重新阅读Github 上的 Byte-Buddy 自述文件,MethodDelegation我发现了使用“GeneralInterceptor”的替代版本。

即具体代理类:

  • 有一个用注释标记的方法RuntimeType

这也很好用!

下面的代码片段演示了这两种技术。

Class<? extends Object> clazz = new ByteBuddy()
    .subclass(serviceSuperClass)
    .name(className) 
    // use a Reflection InvocationHander for the methods of serviceInterfaceOne
    .implement(serviceInterfaceOne)
    .defineField(invocationHandler, MyProxy.class, Visibility.PUBLIC)
    .method(isDeclaredBy(serviceInterfaceOne))
    .intercept(InvocationHandlerAdapter.toField(invocationHandler))
    // use a Byte-Buddy "GeneralInterceptor" for the methods of serviceInterfaceTwo
    .implement(serviceInterfaceTwo)
    .defineField(generalInterceptor, MyProxy.class, Visibility.PUBLIC)
    .method(isDeclaredBy(serviceInterfaceTwo))
    .intercept(MethodDelegation.toField(generalInterceptor))
    //
    .make ()
    .load(classLoader)
    .getLoaded();
Run Code Online (Sandbox Code Playgroud)
public class MyProxy implements InvocationHandler {

  @Override
  public Object invoke(Object serviceImpl, Method method, Object[] args) throws Throwable {
    return null;
  }  

  @RuntimeType
  public Object intercept(@AllArguments Object[] allArguments,
                          @Origin Method method) {
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)

从高层次的角度来看,这两种技术都允许我做同样的事情:

即拦截给定的动态创建的方法到现有的具体方法。

两种解决方案都很优雅,并且所需的代码量相似。

问题是:是否有任何理由更喜欢其中一种而不是另一种?例如性能?功能性?

Raf*_*ter 1

在这种使用形式中,除了委托可以连接到任何(静态或非静态)方法之外没有真正的区别,而调用处理程序适配器仅桥接 Java 代理 API 的实现。这主要意味着如果您已经实现了此类代理处理程序并希望通过 Byte Buddy 重用它们。

Byte Buddy 的处理程序比处理程序 API 提供了更大的灵活性,从而提高了性能,因为如果您知道需要什么参数,您就可以避免数组装箱。它还允许不同的机制,例如调用调用处理程序 API 不支持的默认方法实现。