17 Ekim 2019 Perşembe

SpringAOP @Around Anotasyonu

Giriş
Şu satırı dahil ederiz.
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Around hangi metodları keseceğini kendisine geçilen @Pointcut veya anotasyon ile bulur.

Örnek - execution
Elimizde şöyle bir anotasyon olsun
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE})
public @interface PerformanceLogger {

  TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
Şöyle yaparız
@Aspect
@Component
public class PerformanceLoggerAspect {

  @Around("execution(public * com.emyasa..*(..)) && @target(PerformanceLogger)")
  public void logPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    joinPoint.proceed();
    long timeTakenInMilliseconds = System.currentTimeMillis() - startTime;

    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    Class<?> declaringClass =  methodSignature.getMethod().getDeclaringClass();
    PerformanceLogger logger = declaringClass.getAnnotation(PerformanceLogger.class);

    final String timeUnit;
    final long timeTaken;
    switch (logger.timeUnit()) {
      case MILLISECONDS:
        timeUnit = "ms";
        timeTaken = timeTakenInMilliseconds;
        break;
      case SECONDS:
        timeUnit = "s";
        timeTaken = TimeUnit.MILLISECONDS.toSeconds(timeTakenInMilliseconds);
        break;
      default:
        throw new UnsupportedOperationException("timeUnit unsupported");
      }

     final String logMessage = String.format("%s method took %d %s",
       methodSignature.getMethod().getName(), timeTaken, timeUnit);

      LOGGER.info(logMessage);
  }
}
Örnek - @annotation
Şöyle yaparız. Metodumuzda sadece ProceedingJoinPoint parametresi var.
@Aspect
@Configuration
@RequiredArgsConstructor
@Slf4j
public class TimerCounterAspect {


  @Around("@annotation(br.com.myproject.TimerCount)")
  public Object around(ProceedingJoinPoint joinPoint) {
        
    Object oReturn;
    try {
      oReturn = joinPoint.proceed();
    } catch (Throwable throwable) {
      log.error("...", throwable);
      throw new RuntimeException(throwable);
    } finally {
      ...
    }
    return oReturn;
  }
}
Örnek - @annotation + parametre
Elimizde şöyle bir anotasyon olsun.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Benchmark {

    boolean isEnabled() default true;
}
Şöyle yaparız. Metodumuzda sadece ProceedingJoinPoint ve kendi anotasyonumuz olan Benchmark parametresi var.
@Aspect
@Component
public class BenchmarkingAspect {

  @Around("@annotation(benchmark)")
  public Object benchmarkMethodRuntimeAspect(ProceedingJoinPoint proceedingJoinPoint,
    Benchmark benchmark) throws Throwable {
    if (benchmark.isEnabled()) {
      StopWatch stopWatch = new StopWatch();
      stopWatch.start();
      Object returnedValue = proceedingJoinPoint.proceed();
      stopWatch.stop();
      log.info("Benchmarked: {} from class {}",
        proceedingJoinPoint.getSignature().getName(),
        proceedingJoinPoint.getTarget().getClass().getCanonicalName());
        log.info(stopWatch.prettyPrint());
        return returnedValue;
    } else {
      return proceedingJoinPoint.proceed();
    }
  }
}
Örnek - @annotation
Elimizde şöyle bir anotasyon olsun
@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface LogExecutionTime {

}
Şöyle yaparız. Metodumuzda sadece ProceedingJoinPoint parametresi var.
@Aspect //specifies that this is an aspect
@Component //turn into a bean
public class ExampleAspect {

  @Around("@annotation(LogExecutionTime)")
  public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {

    long start = System.currentTimeMillis(); //executed before the method annotated

    Object proceed = joinPoint.proceed();

    //everything below gets executed after the method.
    long executionTime = System.currentTimeMillis() - start;
    System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");

   return proceed;
  }
}
Örnek
@Pointcut ile şöyle yaparız.
@Component
@Aspect
public class BucketReadPermissionInterceptor {
  @Pointcut("@annotation(com.test.interceptor.ReadPermission)")
  private void readPointcut() {
  }

  @Around("readPointcut()")
  public Response<Object> readCheck(ProceedingJoinPoint joinPoint) {
    Object[] args = joinPoint.getArgs();
    Response<Object> ret = new Response<Object>();
    for (Object object : args) {
      System.out.println("<debug info> " + object);
    }
    try {
      ret = (Response<Object>)joinPoint.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    }
    return ret;
  }
}

Hiç yorum yok:

Yorum Gönder