2010-04-11 38 views
9

Tworzę proxy z javassistem ProxyFactory. Podczas tworzenia pojedynczego proxy wszystko działa dobrze.Javassist: jak utworzyć proxy proxy?

Jednak, gdy mijam proxy obiektu do mechanizmu serwerów proxy, nie jest on z

javassist.bytecode.DuplicateMemberException: powielać metoda: SetHandler w com.mypackage.Bean _ $$ _ _ $$ _ javassist_0 javassist_1

Tworzę serwery proxy z tym:

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

Tak, jak mogę utworzyć proxy proxy?

Update: rzeczywiste problemy, że każdy Pełnomocnik realizuje ProxyObject określający setHandler(..) metody. Drugi serwer proxy próbuje więc przedefiniować metodę, zamiast nadpisywać ją w podklasie.

+0

Przy okazji, wydaje się, że to pierwsze pytanie o javassist. Jestem zaskoczony. – Bozho

Odpowiedz

4

Problem był (właściwie to samo z CGLIB - próbowałem go używając commons-proxy), że nie powinienem próbować tworzyć klasy proxy klasy proxy. Drugie proxy powinno znów być oryginalnej klasy. Więc dodając następującą linię rozwiązuje problem:

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

i porady - jeśli można użyć jakiegoś przechwytujących (jak te zdefiniowane w świetlicy-proxy), wykonaj go zamiast korzystania z wielu serwerów proxy.

1

Jest to dość późno odpowiedzi, ale może nadal być zainteresowany wiedząc o tym:

Javassist proxy są realizowane raczej naiwnie. W swojej powyższym kodzie Javassist zawsze utworzyć klasę proxy z następujących metod:

  1. sposobu dowolnym przeciążać metody klasy bazowej
  2. dwie metody (a) uzyskać obsługi proxy (getHandler) i (b) ustalić obsługi proxy (setHandler)

nazwy tych dwóch ostatnich sposobów są na sztywno przez Javassist reprezentowany przez interfejs ProxyObject. Jeśli utworzysz teraz klasę proxy klasy proxy, Javassist zaplanuje dwa razy tworzenie metod ProxyObject. Raz przez pierwszy warunek i raz przez drugi warunek.

Można tego uniknąć, ustawiając MethodFilter, który określa, aby nie zastępować metod ProxyObject, tak aby javassist tworzyłby tylko metody według drugiego warunku. To jednak sugerowałoby, że nie można dłużej ustawiać ProxyObject dla proxy najwyższej klasy bez bezpośredniego dostępu do odpowiedniego pola poprzez odbicie. Dlatego twoje podejście jest prawdopodobnie najczystsze.

cglib definiuje callbacki na klasę, a nie na przykład takie, że ten problem z cglib jest nieco inny, ale powoduje inny konflikt.

Jeśli jednak chcesz utworzyć klasy proxy, które nie cierpią na te niedociągnięcia, możesz zainteresować się moją biblioteką Byte Buddy, którą napisałem po tym, jak sfrustrowałem pracę z cglib i javassist podczas pracy w przypadkach narożnych. Jeśli pracujesz z generowaniem kodu runtime, mam nadzieję, że może ci to zaoferować pewną elastyczność, której nie mają inne biblioteki.