CGLIB vs Interface Proxy (Spring)

CGLIB vs Interface Proxy (Spring)
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
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


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
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.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Burdzi0
Skąd Ty to wszystko wiesz?! :D
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

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


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
0

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

nie100sowny
  • Rejestracja:około 9 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:402
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:

Kopiuj
public int addNumbers(a, b){
  return a + b;
}
Kopiuj
@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.


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
edytowany 11x, ostatnio: nie100sowny
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
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:

Kopiuj
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.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
0

Dzięki. Tego potrzebowałem :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.