【问题标题】:Byte-Buddy: Method Interception InvocationHandler vs MethodDelegation to GeneralInterceptorByte-Buddy:方法拦截 InvocationHandler 与 MethodDelegation 到 GeneralInterceptor
【发布时间】:2020-02-20 10:33:08
【问题描述】:

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

第一个版本的灵感来自How to create a dynamic proxy using ByteBuddy

它使用反射InvocationHandler

即具体的代理类:

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

这很好用。

然后重新阅读Byte-Buddy readme on Github,我发现了一个使用MethodDelegation 来替代“GeneralInterceptor”的版本。

即具体的代理类:

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

这也很好用!

下面的代码 sn-ps 演示了这两种技术。

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

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

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

两种解决方案都很优雅,所需的代码量也差不多。

问题是:有任何理由偏爱其中一种吗?例如表现?功能?

【问题讨论】:

    标签: java byte-buddy


    【解决方案1】:

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

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

    【讨论】:

    • 好的,所以在拦截方法的具体代理是新代码的情况下,我应该更喜欢 Byte-Buddy "GeneralInterceptor" 而不是 Reflection InvocationHandler。
    • 如果您不需要使用调用处理程序 API,我会推荐它。如果您需要额外的功能,将来可以更轻松地扩展内容。
    • 根据您的回答,我刚刚更改了我的真实代码以使用 Byte-Buddy“GeneralInterceptor”而不是 Reflection InvocationHandler。碰巧反射方法是我发现的第一个可行的解决方案……谢谢。
    • 这两种方法之间的一个区别是,尽管 InnvocationHandler 将所有源方法委托给目标 invoke() 方法,而不管其签名如何,但 Byte Buddy 方法会将一些源方法委托给代理类中的其他方法,而不是预期的(由我)intercept() 方法。为了防止这种额外的字节好友配置,可能需要,如本字节好友 Github 问题github.com/raphw/byte-buddy/issues/814 中所述
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    相关资源
    最近更新 更多