Почему в этом сценарии ByteBuddy делегирует метод «неправильный» метод? - PullRequest
0 голосов
/ 22 марта 2020

Я собираю очень простой класс делегата / прокси ByteBuddy.

Намерение (опять же, очень простое) проксировать класс таким образом, чтобы любой из его не-final, не-private, не static методы и т. д. направляются к эквивалентным методам в его поле proxiedInstance, возвращаемом его методом getProxiedInstance. (Должны быть исключения, сделанные для обычных подозреваемых: equals, hashCode, wait и notify и т. Д.)

Я настроил свой прокси-класс, используя стратегию подкласса. Я также определил два метода, getProxiedInstance и setProxiedInstance, вместе с полем private с именем proxiedInstance соответствующего типа. Я сделал это, используя стратегию FieldAccessor.ofBeanProperty(). Я опустил это здесь для краткости и ясности. Класс действительно содержит это поле и эти два метода.

Затем я определил перехват метода следующим образом, статически импортируя соответствующие ElementMatchers методы:

builder
      .method(not(isFinal()).and(not(isStatic())).and(not(isPrivate()))
              .and((isPublic().and(named("toString")).and(takesArguments(0)).and(returns(String.class)))
                   .or((not(isDeclaredBy(Object.class)).and(not(named("getProxiedInstance"))).and(not(named("setProxiedInstance"))))))
              )
      .intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"));

В английском языке. sh: не final, не static, не private и либо public String toString() метод, унаследованный от Object (или переопределенный), или любой другой метод, не объявленный Object.class и не названный getProxiedInstance или setProxiedInstance.

Предположим, у меня есть такой класс:

public class Frob {

  public String sayHello() {
    return "Hello!";
  }

}

Когда я создаю прокси-класс для него , создать его экземпляр, а затем вызвать toString() на прокси-сервере, я получу Hello!.

Это как-то подсказывает мне, что рецепт, который я цитировал выше, каким-то образом перенаправляет toString() в sayHello().

Из чтения MethodDelegation javadocs кажется, что, возможно, sayHello для объекта назначения / делегата выбрано для делегирования, потому что оно является более точным c, чем метод, вызванный на прокси (toString ). Я думаю, что сопоставление имен имеет более низкий приоритет, чем это.

Я думаю, что этот вариант использования у меня относительно простой. Как мне лучше всего это сделать? 1058 * это?

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

Я думаю, что использование MethodCall - лучший подход к этому. MethodDelegation предназначен для «перехвата всех прокси», когда вы вводите соответствующих диспетчеров в то, что часто является методом с одним делегатом, может быть, двумя. Вызов метода также значительно повышает производительность, поскольку не требует анализа, а просто перенаправляет метод совместимого типа.

0 голосов
/ 22 марта 2020

Лучшее, что я мог сделать, что работает, но, возможно, кажется немного неуклюжим или многословным, это:

builder = builder
      .method(not(isDeclaredBy(Object.class))
              .and(not(isFinal()))
              .and(not(isStatic()))
              .and(not(isPrivate()))
              .and(not(named("getProxiedInstance")))
              .and(not(named("setProxiedInstance"))))
      .intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"))
      .method(is(toStringMethod))
      .intercept(invoke(toStringMethod).onMethodCall(invoke(named("getProxiedInstance"))));

(toStringMethod - это Method, полученное из Object.class.getMethod("toString").)

...