2010-04-11 18 views
9

Estoy creando proxies con javassist ProxyFactory. Al crear un solo proxy, todo funciona bien.Javassist: ¿cómo crear proxy de proxy?

Sin embargo, al pasar un objeto proxy al mecanismo de proxy, falla con

javassist.bytecode.DuplicateMemberException: duplicar método: SetHandler en com.mypackage.Bean _ $$ _ javassist_0 _ $$ _ javassist_1

estoy creando los proxies con esto:

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

Entonces, ¿cómo puedo crear proxies de proxy?

Actualización: Los problemas reales es que cada proxy implementa el ProxyObject que define setHandler(..) método. Por lo tanto, el segundo proxy intenta redefinir el método, en lugar de anularlo en la subclase.

+0

por cierto, esta parece ser la primera pregunta sobre javassist. Estoy sorprendido. – Bozho

Respuesta

4

El problema era (en realidad, es lo mismo con CGLIB - Lo probé usando commons-proxy) que no debería intentar crear una clase proxy de la clase proxy. El segundo proxy debería volver a ser de la clase original. Por lo que añadir la siguiente línea resuelve el problema:

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

Y un consejo - si se puede usar algún tipo de interceptores (como los definidos en Commons-proxy), hacerlo en lugar de utilizar múltiples servidores proxy.

1

Es una respuesta bastante tarde, pero todavía puede estar interesado en saber esto:

proxies Javassist se implementan con bastante ingenuidad. En el código anterior, Javassist siempre va a crear una clase de proxy con los siguientes métodos:

  1. Un método para cualquier método reemplazable de la clase base
  2. Dos métodos para: (a) obtener un controlador de proxy (getHandler) y (b) establecer un controlador de proxy (setHandler)

los nombres de los dos últimos métodos están codificados por Javassist y representados por la interfaz ProxyObject. Si ahora creas una clase proxy de una clase proxy, Javassist programaría la creación de los métodos ProxyObject dos veces. Una vez por la primera condición y una vez por la segunda condición.

Puede evitar esto estableciendo un MethodFilter que especifica no anular los métodos de ProxyObject de modo que javassist solo cree los métodos por la segunda condición. Sin embargo, esto implicaría que ya no podría establecer un ProxyObject para el proxy de la clase superior sin acceder directamente al campo correspondiente a través de la reflexión. Por lo tanto, su enfoque es probablemente el más limpio.

cglib define las devoluciones de llamada por clase y no por instancia, por lo que este problema con cglib es ligeramente diferente pero da como resultado otro conflicto.

Sin embargo, si desea crear clases de proxy que no presenten estas deficiencias, podría estar interesado en mi biblioteca Byte Buddy que escribí después de frustrarme trabajando con cglib y javassist cuando trabajé en casos de esquina. Si está trabajando con la generación de código de tiempo de ejecución, espero que pueda ayudar a ofrecerle cierta flexibilidad de la que carecen las otras bibliotecas.