Byte-Buddy: метод перехвата InvocationHandler vs MethodDelegation для GeneralInterceptor - PullRequest
3 голосов
/ 20 февраля 2020

Я использую Byte-Buddy для динамической генерации реализаций методов интерфейса Java и для делегирования вызовов этих методов одному методу существующего прокси-объекта.

Первая версия была вдохновлена Как создать динамический c прокси с помощью ByteBuddy

Используется Reflection InvocationHandler

, то есть конкретный прокси-класс:

  • реализует интерфейс InvocationHandler
  • переопределяет метод invoke()

Это прекрасно работает.

Затем перечитайте Byte-Buddy readme на Github я обнаружил альтернативную версию, использующую 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();
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;
  }
}

С точки высокого уровня -видеть обе техники позволяют мне делать одно и то же:

т.е. перехватывать с учетом динамически создаваемых методов к существующему конкретному методу.

Оба решения элегантны, и объем требуемого кода аналогичен.

Вопрос: есть ли причина отдавать предпочтение одному из них? Другой? например, производительность? Функциональность

1 Ответ

1 голос
/ 21 февраля 2020

В этой форме использования нет никакой реальной разницы, за исключением того, что делегирование может быть связано с любым (stati c или non-stati c) методом, тогда как адаптер обработчика вызовов только соединяет реализации для Java ' с прокси API. Это в основном подразумевается, если вы уже реализовали такие прокси-обработчики и хотите использовать их с Byte Buddy.

Обработчик Byte Buddy обеспечивает большую гибкость, чем API-обработчик, что повышает производительность, поскольку вы можете, например, избежать упаковки массива, если Вы знаете, какие аргументы ожидать. Это также позволяет использовать различные механизмы, такие как вызов реализации метода по умолчанию, который API-интерфейс обработчика вызовов не поддерживает.

...