Pergunta

Estou criando proxies com javassist ProxyFactory. Ao criar um único proxy, tudo funciona bem.

No entanto, quando passo um objeto proxado para o mecanismo de proxy, ele falha com

javassist.bytecode.duplicatememberexception: Duplicate Método: Sethandler em com.mypackage.bean _ $$ _ javassist_0 _ $$ _ javassist_1

Estou criando os proxies com isso:

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

Então, como faço para criar proxies de proxies?

Atualizar: Os problemas reais são que cada proxy implementa o ProxyObject que define setHandler(..) método. Portanto, o segundo proxy está tentando redefinir o método, em vez de substituí -lo na subclasse.

Foi útil?

Solução

O problema era (na verdade, é o mesmo com o CGLIB - eu tentei usando o Commons -Proxy) que não deveria tentar criar uma classe proxy da classe proxy. O segundo proxy deve ser novamente da classe original. Portanto, a adição da linha a seguir resolve o problema:

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

E um conselho - se você pode usar algum tipo de interceptores (como os definidos no Commons -Proxy), faça -o em vez de usar vários proxies.

Outras dicas

É uma resposta bastante tardia, mas você ainda pode estar interessado em saber disso:

Os proxies javassistas são implementados ingenuamente. No seu código acima, o Javassist sempre criará uma aula de proxy com os seguintes métodos:

  1. Um método para qualquer método substituível da classe base
  2. Dois métodos para (a) obter um manipulador de proxy (getHandlere (b) definir um manipulador de proxy (setHandler)

Os nomes dos dois últimos métodos são codificados por Javassist e representados pelo ProxyObject interface. Se agora você criar uma classe de proxy de uma aula de proxy, Javassist agendará a criação de ProxyObjectMétodos duas vezes. Uma vez pela primeira condição e uma vez pela segunda condição.

Você pode evitar isso definindo um MethodFilter que especifica para não substituir o ProxyObjectOs métodos de modo que o Javassist apenas criaria os métodos pela segunda condição. No entanto, isso implicaria que você não poderia mais definir um ProxyObject Para o proxy de super classe sem acessar diretamente o campo correspondente por reflexão. Portanto, sua abordagem é provavelmente a mais limpa.

O CGLIB define retornos de chamada por classe e não por instância, de modo que esse problema com o CGLIB seja um pouco diferente, mas resulta em outro conflito.

No entanto, se você deseja criar aulas de proxy que não sofrem essas deficiências, você pode estar interessado na minha biblioteca Byte Buddy que escrevi depois de ficar frustrado trabalhando com CGLIB e Javassist ao trabalhar em casos de esquina. Se você estiver trabalhando com a geração de código de tempo de execução, espero que isso ajude a oferecer alguma flexibilidade que as outras bibliotecas não possuam.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top