27 Ocak 2021 Çarşamba

SpringAOP Kullanımı

Giriş
SpringAOP Kavramları yazısına bakabilirsiniz.

Maven
Şu satırı dahil ederiz.
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Spring ile Aspect Oriented Programlama Yapmak için iki seçenek var.
1. Spring AOP
2. AspectJ. AspectJ varsayılan yöntem değil, çünkü yavaş. Açıklaması şöyle.
AspectJ is a runtime resolution, which has a performance drawback.
AspectJ için şu satırı dahil ederiz
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
</dependency>
Spring AOP
SpringAOP sadece bean'ler üzerinde kullanılabilir. Açıklaması şöyle.
Spring AOP runs everything through proxies which sadly can't be everywhere.
....
Proxies are created only for singletons (@Bean) so we are greatly limited when we want to secure methods on specific objects (such as JPA @Entities) that are not beans. Proxies also won't be called within calling objects (bean calling its methods in context of self - this).
Kullanım
1. Bir @Aspect sınıfı oluşturulur. Bu sınıfın Spring ayağa kalkarken bulunuyor olması gerekir.
2. Bu sınıf içinde @Pointcut ile hangi metodların seçileceği belirtilir.
3. Daha sonra Advice ile Pointcut birbirlerine sağlanır. Temel olarak 3 çeşit advice vardır. Bunlar şöyle
- @Before Advice 
- @After Advice
- @Around Advice

@AfterThrowing de bir advice'tır ancak temel kullanıma dahil etmedim.

@Before ile @Pointcut ile seçilen metodlardan önce kod çalıştırılabilir. @Before Anotasyonu yazısına bakabilirsiniz.

@After ile @Pointcut ile seçilen metodlardan sonra kod çalıştırılabilir. @After Anotasyonu yazısına bakabilirsiniz.

@Around ile @Pointcut ile seçilen metodlardan önce ve sonra kod çalıştırılabilir. 

6. @AfterThrowing ile @Pointcut ile seçilen metodlardan exception fırlatılınca kod çalıştırılabilir. 

Örnek
Şöyle yaparız. Burada özel bir @Pointcut tanımlanmıyor. @Before advice içine @LogMethod anotasyonuna sahip metodlar tanımlanıyor.
@Aspect
@Component
public class LoggingAspect {

  @Before("@annotation(LogMethod)")
  public void logMethodName(JoinPoint joinPoint) {
    String method = joinPoint.getSignature().getName();
    String params = Arrays.toString(joinPoint.getArgs());
    System.out.println("Method [" + method + "] gets called with parameters " + params);
  }
}
Örnek
Şöyle yaparız. Burada 3 tane @Pointcut var ve metodların için boş. 
- Daha sonra @Before advice ile pointcut bağlanıyor
- @AfterThrowing advice ile pointcut bağlanıyor
@Aspect
public class LoggingAspect {

@Pointcut("execution(* com.tlc.tracker.v01.controller.*.*(..))")
public void controllerMethods() { }

@Pointcut("execution(* com.tlc.tracker.v01.service.imp.ProjectServiceImpl.*(..))")
public void serviceMethods(){  }

@Pointcut("execution(* com.tlc.tracker.v01.repository.*.*(..))")
public void respositoryMethods(){  }

@Before("serviceMethods()")
public void Areturn(JoinPoint point){
    System.out.println("Hola");
    log.info("HOLA");
}

@AfterThrowing(pointcut = "controllerMethods() && serviceMethods() 
  && respositoryMethods()", throwing = "exception")
public void logAfterThrowing(JoinPoint joinPoint, Throwable exception){

  if(exception instanceof BusinessServiceException){
    //Get the parts of the exception message
    String exceptions[] = exception.getMessage().split(":", 2);
    //Get the message contained in the exception message
    String message = exceptions.length == 1 ? "" : exceptions[1];

    log.error("[" + joinPoint.getSignature().getName() 
      + "] - Type: " + exceptions[0] + ". Message: "+ message);
  }

  if(exception instanceof Exception){
    log.error("[" + joinPoint.getSignature().getName()
      + "] - Type: ServerError. Message: "  + exception.getMessage());
  }
}

Hiç yorum yok:

Yorum Gönder