Spring AOP - AspectJ

AspectJ to pierwszy język AOP ogólnego przeznaczenia, który stał się na tyle dobry, że zyskał znaczenie w kontekście budowy aplikacji biznesowych. Oryginalnie został stworzony przez firmę PARC (Xerox PARC), specjalizującą się w R&D. Aby zachęcić do rozwoju technologii AspectJ, w grudniu 2002 PARC przekazało AspectJ do zdobywającego coraz większą popularność, otwartego projektu eclipse.org. Na początku AspectJ bazował na regularnych klasach, nie był budowany w oparciu o adnotacje. Zmieniło się to dopiero razem z wydaniem wersji AspectJ 5, gdzie po raz pierwszy został wprowadzony styl @AspectJ.

Spring AOP używa biblioteki dostarczonej przez AspectJ, co pozwala mu na interpretowanie tych samych adnotacji co AspectJ 5. Środowisko AOP jest środwiskiem czysto Springowym i nie zależy od kompilatora AspectJ, ani od jego tkacza (Weaver). Używa za to jego biblioteki do analizowania i dopasowywania punktów.

Jeśli chcemy korzystać z AOP w Spring Boot, musimy najpierw podpiąć zależność szablonu startowego aop:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Po zbudowaniu projektu możemy przystąpić do implementowania swojego pierwszego aspektu.

Spring AOP - Porada @Around w akcji

Pokażemy teraz na przykładzie, jak teoria aspektów wygląda w praktyce. Chcemy stworzyć aspekt używając adnotacji pochodzącej z biblioteki AspectJ, który to aspekt będzie posiadał poradę typu Around Advice (Porada Dookoła) i będzie wykorzystywany do logowania czasów wykonania metod w aplikacji webowej:
@Aspect
public class LogAspect {

    private static final Logger LOG = LoggerFactory.getLogger(LogAspect.class);
    
    private final String SERVICE_POINTCUT = "execution(* com.javappa.startappa.appaadmin.service.*.*(..))";
    
    @Around(SERVICE_POINTCUT)
    public Object logAdvice(ProceedingJoinPoint jp) throws Throwable {
    
        LOG.info("[METHOD] --------> {}", jp.getSignature().toShortString());
        
        Object[] signatureArgs = jp.getArgs();
        for (Object signatureArg : signatureArgs) {
        	LOG.info("[ARGS] --------> {}: {}", signatureArg.getClass().getSimpleName(), 
                                                    signatureArg.toString());
        }
        
        Instant startTime = Instant.now();
        Object obj = jp.proceed();
        Instant endTime = Instant.now();
        
        LOG.info("[METRICS] --------------------> {}, time: {} {} ", jp.getSignature().toShortString(),
        		Duration.between(startTime, endTime).getSeconds(), "sec.");
        
        return obj;
    }
}
Wskażemy teraz najważniejsze elementy aspektowe, przedstawione w tym przykładzie:
  • Aspekt, reprezentowany przez adnotację @Aspect.
  • Porada Dookoła (Around Advice), reprezentowana przez adnotację @Around.
  • Punkt przecięcia (Pointcut), reprezentowany przez stałą SERVICE_POINTCUT, będącą parametrem adnotacji @Around.
  • Punkt złączenia (Join point), reprezentowany przez parametr metody ProceedingJoinPoint.

Podsumujmy. Widzimy na przykładzie klasę, która dzięki oznaczeniu jej adnotacją @Aspect, staje się aspektem. Następnie w ramach tej klasy mamy metodę (logAdvice) oznaczoną adnotacją @Around, która jest poradą uruchamianą tylko dla konkretnego zestawu klas, określanego przez paradygmat SERVICE_POINTCUT.

Metoda będzie uruchamiana za każdym razem gdy uruchamiania będzie dowolna metoda z pakietu service. Dodatkowo, dzięki temu że w metodzie naszej porady otrzymujemy dostęp do punktu złączenia, uzyskujemy nad nim kontrolę. Tak więc mamy możliwość najpierw wykonać operację logowania nazwy metody wraz z jej parametrami, zapisać bieżący czas, a następnie uruchomić faktyczną metoodę serwisu (jp.proceed). Na końcu, po wykonaniu metody serwisowej wyliczamy czas jaki upłynął podczas wykonywania tej metody.
Rekomendacja
Mierzenie czasu wykonania metod stanowi kluczowy element w monitorowaniu wydajności aplikacji, szczególnie po jej wdrożeniu na środowisko produkcyjne. Implementując taki mechanizm, można również włączyć funkcję powiadamiania, na przykład przez wysyłanie emaili na dedykowane konto serwisowe, gdy czas wykonania metody przekracza ustalony próg.

Ważne jest jednak, aby ten maksymalny czas wykonania był ustalony w sposób przemyślany, aby uniknąć nadmiernego powiadamiania i skupić się na sytuacjach rzeczywiście wyjątkowych, wymagających uwagi.
Praktyka


Aspekt zaprezentowany w przykładowym kodzie jest integralną częścią każdego modułu naszej aplikacji. Oznacza to, że po pobraniu i uruchomieniu aplikacji z Kursu Aplikacji Web - Mega pakiet, użytkownik otrzymuje na konsoli szczegółowe informacje dotyczące czasów wykonania poszczególnych metod, które są wykorzystywane w ramach kursu.
Zdjęcie autora
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
Topowe Materiały
Spring IO: Aspect Oriented Programming with Spring
Baeldung: Introduction to Spring AOP
Baeldung: Comparing Spring AOP and
Baeldung: Implementing a Custom Spring AOP Annotation
Jstobigdata: Complete Spring AOP Tutorial

Udemy: [NEW] Spring Boot 3, Spring 6 & Hibernate for Beginners  —  polskie napisy

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE