2010-04-11 44 views
9

Sto creando dei proxy con javassist ProxyFactory. Quando si crea un singolo proxy, tutto funziona correttamente.Javassist: come creare il proxy del proxy?

Tuttavia, quando passo davanti a un dell'oggetto proxy per il meccanismo di proxy, non riesce con

javassist.bytecode.DuplicateMemberException: Metodo di duplicazione: SetHandler in com.mypackage.Bean _ _ $$ javassist_0 _ _ $$ javassist_1

sto creando delle deleghe con questo:

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

Allora, come faccio a creare i proxy di proxy?

Aggiornamento: I problemi reali è che ogni delega implementa l'ProxyObject che definisce setHandler(..) metodo. Quindi il secondo proxy sta cercando di ridefinire il metodo, invece di sovrascriverlo nella sottoclasse.

+0

btw, questa sembra essere la prima domanda su javassist. Sono sorpreso. – Bozho

risposta

4

Il problema era (in realtà, è lo stesso con CGLIB - l'ho provato usando commons-proxy) che non dovrei provare a creare una classe proxy della classe proxy. Il secondo proxy dovrebbe essere di nuovo della classe originale. Quindi aggiungendo la riga seguente risolve il problema:

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

E un consiglio - se è possibile utilizzare una sorta di intercettori (come quelli definiti nel commons-proxy), farlo invece di utilizzare più proxy.

1

sua una risposta piuttosto tardi, ma si potrebbe ancora essere interessati a conoscere questo:

Javassist proxy sono implementate piuttosto ingenuamente. Nel codice precedente, Javassist sarà sempre creare una classe proxy con le seguenti modalità:

  1. Un metodo per qualsiasi metodo override della classe base
  2. due metodi per (a) ottenere un gestore di proxy (getHandler) e (b) impostare un gestore proxy (setHandler)

i nomi di questi ultimi due metodi sono fissi da Javassist e rappresentato dall'interfaccia ProxyObject. Se ora crei una classe proxy di una classe proxy, Javassist pianificherà la creazione dei metodi di ProxyObject due volte. Una volta dalla prima condizione e una volta dalla seconda condizione.

È possibile evitare questo impostando un MethodFilter che specifica di non sovrascrivere i metodi di ProxyObject in modo che javassist crei solo i metodi in base alla seconda condizione. Tuttavia, ciò implicherebbe che non è possibile impostare un valore di ProxyObject per il proxy super-classe senza accedere direttamente al campo corrispondente tramite riflessione. Pertanto, il tuo approccio è probabilmente il più pulito.

cglib definisce i callback per classe e non per istanza tale che questo problema con cglib sia leggermente diverso ma si traduca in un altro conflitto.

Tuttavia, se si desidera creare classi proxy che non presentano queste carenze, potrebbe essere interessato alla mia libreria Byte Buddy che ho scritto dopo essersi frustrata lavorando con cglib e javassist quando si lavora in casi d'angolo. Se stai lavorando con la generazione del codice di runtime, spero che possa aiutarti a offrirti una certa flessibilità rispetto alle altre librerie.

Problemi correlati