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.
Nasza rekomendacja
Mierzenie czasu wykonania metod może być bardzo pomocne szczególnie w przypadku gdy aplikacja zostanie już wdrożona na produkcję. Można do takiego mechanizmu dodać na przykład wysyłanie maila na konto serwisowe, w przypadku gdy wykonanie metody przekracza określony dla niej maksymalny czas wykonania. Czas taki należy oczywiście określić rozsądnie, aby mail był wysyłany tylko w wyjątkowych sytuacjach.
Używamy w StartAPPa


Aspekt przedstawiony w przykładzie jest przez nas wykorzystywany w każdym module aplikacji. Tak więc ściągając dowolny kurs i uruchamiając załączony projekt, dostajecie na konsoli informacje o czasach wykonań metod wykorzystywanych w kursie.
Linki
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop
http://web.archive.org/web/20090225004835/http://www.parc.com/research/projects/aspectj

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