Javassist: как создать прокси прокси? - PullRequest
9 голосов
/ 12 апреля 2010

Я создаю прокси с javassist ProxyFactory.При создании одного прокси все работает нормально.

Однако, когда я передаю прокси-объект в механизм прокси, он завершается с

javassist.bytecode.DuplicateMemberException: дублирующий метод: setHandlerв com.mypackage.Bean _ $$ _ javassist_0 _ $$ _ javassist_1

Я создаю прокси с этим:

public Object createProxiedInstance(Object originalInstance) throws Exception {
    Class<?> originalClass = instance.getClass();
    ProxyFactory factory = new ProxyFactory();

    factory.setSuperclass(originalClass);

    factory.setHandler(new MethodHandler() {..});
    Class<T> proxyClass = factory.createClass();

    return proxyClass.newInstance();
}

Итак, как мне создать прокси прокси?

Обновление: Фактическая проблема заключается в том, что каждый прокси-сервер реализует ProxyObject, который определяет метод setHandler(..).Таким образом, второй прокси пытается переопределить метод, а не переопределять его в подклассе.

Ответы [ 2 ]

4 голосов
/ 13 апреля 2010

Проблема была (на самом деле, то же самое с CGLIB - я пробовал это с помощью commons-proxy), что я не должен пытаться создать прокси-класс прокси-класса. Второй прокси снова должен быть оригинального класса. Таким образом, добавление следующей строки решает проблему:

if (instance instanceof ProxyObject) {
    originalClass = originalClass.getSuperclass();
}

И совет - если вы можете использовать какие-то перехватчики (например, определенные в commons-proxy), сделайте это вместо использования нескольких прокси.

1 голос
/ 03 мая 2014

Ответ довольно поздний, но вам, возможно, будет интересно узнать это:

Javassist прокси реализованы довольно наивно. В приведенном выше коде Javassist всегда создает прокси-класс со следующими методами:

  1. Метод для любого переопределяемого метода базового класса
  2. Два способа (а) получить обработчик прокси (getHandler) и (б) установить обработчик прокси (setHandler)

Имена двух последних методов жестко закодированы Javassist и представлены интерфейсом ProxyObject. Если вы сейчас создадите прокси-класс прокси-класса, Javassist запланирует создание методов ProxyObject дважды. Один раз по первому условию и один раз по второму условию.

Этого можно избежать, установив MethodFilter, который указывает, что не следует переопределять методы ProxyObject, чтобы javassist создавал методы только по второму условию. Однако это будет означать, что вы больше не сможете установить ProxyObject для прокси суперкласса без прямого доступа к соответствующему полю через отражение. Поэтому ваш подход, вероятно, самый чистый.

cglib определяет обратные вызовы для каждого класса, а не для каждого экземпляра, так что эта проблема с cglib немного отличается, но приводит к другому конфликту.

Однако, если вы хотите создать прокси-классы, которые не страдают этими недостатками, вас может заинтересовать моя библиотека Byte Buddy , которую я написал после того, как разочаровался в работе с cglib и javassist при работе в угловых случаях , Если вы работаете с генерацией кода во время выполнения, я надеюсь, что это поможет вам предложить некоторую гибкость, которой не хватает другим библиотекам.

...