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
- Rejestracja:ponad 10 lat
- Ostatnio:6 miesięcy
- Lokalizacja:Warszawa
- Postów:3573

- Rejestracja:około 21 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Space: the final frontier
- Postów:26433
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.


- Rejestracja:prawie 9 lat
- Ostatnio:4 dni
- Lokalizacja:Kraków
- Postów:402
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.

- Rejestracja:około 21 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Space: the final frontier
- Postów:26433
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.