CGLIB vs Interface Proxy (Spring)

0

W Springu stosuje się proxy, na ogół są to interfejsy. Zastanawiam się czy oprócz powodów historycznych i ułatwiania testów, ma to jakieś inne zalety? Jaki to ma wpływ na performance?
@Shalom pewnie masz coś ciekawego do powiedzenia :D

0

Interface Proxy jest dużo łatwiejsze w implementacji, stąd było dostępne standardowo, a class proxy wymagało cgliba bo wiąże sie z czarną magią w bajtkodzie.

0

Ale teraz chyba jest dosyć łatwo, wystarczy odpowiednia adnotacja

0

A może ktoś napisać łopatologicznie różnice między JDK proxy, CGLIB proxy, AspectJ/AoP ?

2

AOP - Aspect Oriented Programming - w skrócie technika polegająca na tym, że mając już jakieś klasy z logiką, piszesz do nich aspekty, czyli osobny kod, który wywoła się przed / po / na około metody. Definiuje się tam specjalnymi wzorcami, które klasy i metody zostaną okryte dodatkową logiką, czyli aspektem.

Często tą dodatkową logiką jest bezpieczeństwo / logowanie / transakcje, czyli tzw. Cross-cutting concerns.

AspectJ to biblioteka implementująca AOP na etapie kompilacji. Czyli definiujesz specjalne pliki (chyba teraz w klasach Javy też można) i kompilator wklei CI na około metod kodzik - taki kopiuj wklej na bytecode.

Spring AOP to biblioteka implementująca AOP na atapie wykonania. Czyli masz klasy i zostaną one oklejone aspektami podczas uruchamiania. I tutaj są dwie opcje:
JDK proxy (default) - lżejsze i chyba bardziej przenośne, ale wymaga aby klasa implementowałą interfejs.
CGLIB - polega na manipulacji bytecode, rozszerzaniu docelowych klas i prawdopodobnie wykorzystuje jakieś haki w JVM.

Pseudokod:

public int addNumbers(a, b){
  return a + b;
}
@Around("bla bla bla skomplikowany wzorzec określający, które metody to przechwyci")
public Object logAllAdditions(JoinPoint joinpoint){
    Class target = joinpoint.getTargetClassCzyJakośTak();
    Object[] args = joinpoint.getArgumentsCzyJakośTak();
    log.info("Ktuś cuś dodaje w {} {}", target, args);
    return 0 // ha ha ha nikt nie będzie wiedział czemu wszystkie dodawania zwracają 0
}

Tyle pamiętam z głowy, jak się mylę to poprawcie.

3

Generalnie JDK Proxy i CGLIB Proxy są wykorzystywane do "implementowania" w praktyce AOP w kodzie. Dajesz np. nad metodą @Transactional i magicznie przed metodą wykona się otwarcie transakcji a po metodzie zostanie ona zamknięta i commitowana.
No tylko że tutaj nie ma żadnej magii i nie trudno sobie wyobrazić jak to się implementuje. Robimy po prostu "w locie" klasę rozszerzającą tą klase z naszym @Transactional (albo inną AOPową magią) / implementującą ten sam interfejs i overridujemy tą wybraną metodę, tak że nowa implementacja to:

public T someMethod(){
     transaction.open();
     T result = super.someMethod(); // albo delegate.someMethod();
     transaction.commit();
     return result
}

albo coś w tym stylu i voila.
Tak generalnie działa Interface proxy, bo zaimplementowanie interfejsu to nie problem i wrzucenie do tej nowej klasy referencji do oryginalnego obiektu (żeby delegować wywołania) to też nie problem.

Problem przez długi czas był z class proxy no bo co jak klasa jest np. final czyli z definicji nie da się jej rozszerzać? Z pomocą przyszedł cglib który pozwalał poczarować w bajtkodzie i w locie zmienić klasę z finalnej na nie finalną i zrobić proxy które ją rozszerzało.

0

Dzięki. Tego potrzebowałem :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1