2010-04-11 9 views
9

Ich erstelle Proxies mit Javassist ProxyFactory. Beim Erstellen eines einzelnen Proxy funktioniert alles einwandfrei.Javassist: wie Proxy-Proxy erstellen?

Wenn jedoch ich ein Proxy-Objekt zum Proxying Mechanismus übergeben, schlägt es mit

javassist.bytecode.DuplicateMemberException: duplicate Methode: SetHandler in com.mypackage.Bean _ $$ _ _ javassist_0 $$ _ javassist_1

ich schaffe die Proxys mit diesem:

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

So, wie erstelle ich Proxies von Proxies?

Update: Die eigentlichen Probleme ist, dass jeder Proxy die ProxyObject implementiert die setHandler(..) Methode definiert. Daher versucht der 2. Proxy die Methode neu zu definieren, anstatt sie in der Unterklasse zu überschreiben.

+0

BTW, scheint dies die erste Frage über Javassist zu sein. Ich bin überrascht. – Bozho

Antwort

4

Das Problem war (eigentlich ist es das gleiche mit CGLIB ist - ich versuchte es mit commons-Proxy), dass ich nicht versuchen sollte, eine Proxy-Klasse der Proxy-Klasse zu erstellen. Der zweite Proxy sollte wieder der ursprünglichen Klasse angehören. So fügen Sie folgende Zeile löst das Problem:

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

Und einen Rat - wenn Sie irgendeine Art von Abfangjäger verwenden können (wie die definierte in commons-Proxy), tun Sie es stattdessen mehrere Proxys zu verwenden.

1

Es ist eine ziemlich spät Antwort, aber man könnte noch diese daran interessiert zu wissen:

Javassist Proxies umgesetzt werden eher blauäugig. In Ihrem obigen Code Javassist wird immer eine Proxy-Klasse mit den folgenden Methoden erstellen:

  1. Verfahren für jede überschreibbare Methode der Basisklasse
  2. zwei Methoden, um (a) erhält einen Proxy-Handler (getHandler) und (b) setzen eines Proxy-Handler (setHandler)

die Namen der beiden zuletzt genannten Verfahren werden durch Javassist einprogrammiert und dargestellt durch die ProxyObject Schnittstelle. Wenn Sie jetzt eine Proxy-Klasse eines Proxy-Klasse erstellen, würde Javassist zweimal die Schaffung ProxyObject ‚s Methoden planen. Einmal bei der ersten Bedingung und einmal bei der zweiten Bedingung.

Sie können dies vermeiden, indem Sie eine MethodFilter setzen, die angibt, dass die Methoden ProxyObject nicht überschrieben werden sollen, sodass javassist die Methoden nur durch die zweite Bedingung erstellen würde. würde dies bedeutet jedoch, dass Sie nicht mehr ProxyObject für das Super-Klasse-Proxy einstellen konnten, ohne direkt durch Reflexion auf das entsprechende Feld zugreifen. Daher ist Ihr Ansatz wahrscheinlich der sauberste.

cglib definiert Rückrufe pro Klasse und nicht pro Instanz so, dass dieses Problem mit cglib etwas anders ist, führt aber zu einem anderen Konflikt.

Wenn Sie jedoch Proxy-Klassen erstellen möchten, die diese Mängel nicht aufweisen, interessiert Sie möglicherweise meine Bibliothek Byte Buddy, die ich nach dem frustrierten Arbeiten mit cglib und javassist bei der Arbeit in eckigen Fällen geschrieben habe. Wenn Sie mit der Generierung von Runtime-Code arbeiten, hoffe ich, dass Sie dadurch eine gewisse Flexibilität erhalten, die den anderen Bibliotheken fehlt.