Java

Spring Boot #17 – Programowanie zorientowane aspektowo (AOP)

Spring Boot

Programowanie zorientowane aspektowo (AOP) to podejście do programowania, które umożliwia przechwycenie działań wskazanej metody, w celu uruchomieniu jakiegoś fragmentu kodu przed lub po logice wykonującej się w przechwytywanej metodzie.

Przykład

Przykładowo jest metoda foo, której zadaniem jest zapis informacji i wyświetlenie komunikatu o zapisaniu. W tradycyjnym podejściu jedną metodę zapisuje się jedna pod drugą.


public void foo() {
    save();
    System.out.println("saved");
}

W AOP dąży się do czystości kodu, poprzez izolacje odpowiedzialności. Metody robią to tylko za co są odpowiedzialne, nie miesza się logik jakimi są zapisywanie i wypisywanie informacji w oknie konsoli.

W podejściu AOP metoda foo zapisuje jedynie informacje. Inna metoda odpowiedzialna za wypisywanie tekstu na ekranie nasłuchuje metodę foo i kiedy foo skończyło swoją pracę to metoda nasłuchująca wykonuje swoje działanie.

Implementacja

Zależnością jaką trzeba dodać do projektu jest:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Zależność umożliwia na między innymi na wykorzystanie trzech kluczowych porad, które w parametrze przyjmują ścieżkę do metody jaka ma zostać przechwycona:

  • @Around – Metoda oznaczona tą adnotacją wykona się przed lub zamiast metody wskazanej w parametrze.
  • @Before – Metoda oznaczona tą adnotacją wykona się przed metodą wskazaną w parametrze.
  • @After – Metoda oznaczona tą adnotacją wykona się po metodzie wskazanej w parametrze.

Metoda, którą chcemy przechwycić to metoda sayHello

public String sayHello() {
    return "Hello " + "";
}

Żeby stworzyć możliwość jej przechwycenia trzeba utworzyć klasę z adnotacjami:

  • @Aspect
  • @Component
@Aspect
@Component
public class HelloAspect {

    @Around("@annotation(Hello)")
    public void aroundHello(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("aroundHello");
        joinPoint.proceed();
    }

    @Before("@annotation(Hello)")
    public void beforeHello() {
        System.out.println("beforeHello");
    }

    @After("execution(String pl.bykowski.springbootaop.HelloApi.sayHello())")
    public void afterHello() {
        System.out.println("afterHello");
    }
}

W poniższym przypadku zostały zaimplementowane trzy metody (zwane również poradami). W przypadku wywołania metody sayHello kolejno uruchomią się metody:

  1. aroundHello
  2. beforeHello
  3. sayHello
  4. afterHello

Warto zwrócić uwagę, że porada @Around przyjmuje w parametrze ProceedingJoinPoint. Dzięki temu, możliwe jest przekazanie wątku dalej do metody przechwytywanej. Bez wywołania joinPoint.proceed() to metoda przechwytywana nie wykonałaby się. Takie działanie może mieć swoje uzasadnienie w wybranych przypadkach.

Podsumowanie

Programowanie zorientowane aspektowo pozwala zachować czytelność kodu. Jednak odbywa się to kosztem zaburzenia naturalnego przepływu działania programu i jest w sprzeczności z zasadami programowania obiektowego. Dlatego należy stosować AOP rozsądnie i przemyślanie. Najczęściej wykorzystuje się go do logowania informacji lub zabezpieczeń.

Tags:
Show Buttons
Hide Buttons