스프링 레시피 CH2.16 애스펙트 포인트컷 재사용하기

2023. 12. 18. 21:38spring

과제

포인트컷 표현식을 여러 번 되풀이해서 쓸 겨웅엔 어드바이스 애너테이션에 직접 써넣는 것보다 재사용할 방법이 필요하다.

 

해결책

@Pointcut을 이용하면 포인트컷만 따로 정의해 여러 어드바이스에서 재사용할 수 있다.

풀이

애스펙트에서 포인트컷은 @Pointcut을 붙인 단순 메서드로 선언할 수 있다. 포인트컷과 애플리케이션 로직이 뒤섞이는 건 바람직하지 않으니 메서드 바디는 보통 비워두고 포인트컷의 가시성은(public, protected, private) 메서드의 수정자로 조정한다.

 

이렇게 선언된 포인트컷은 다른 어드바이스가 메서드명으로 참조한다.

package com.spring.study.chapter02.aop.calculation._aspect.log;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Aspect
public class CalculatorLoggingAspect {

    private final Log log = LogFactory.getLog(this.getClass());
    @Pointcut("execution(* *.*(..))")
    private void loggingOperation() {}


    @Around("loggingOperation()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("the method() {}" + joinPoint.getSignature().getName()
                +" begins with {}" + Arrays.toString(joinPoint.getArgs()));

        try{
            Object result = joinPoint.proceed();
            log.info("the method : {}" + joinPoint.getSignature().getName()
                   + "ends with : {}" + result);
            return result;
        } catch (IllegalArgumentException e) {
            log.error("Illegal argument : {}" + Arrays.toString(joinPoint.getArgs())
                    + "method with : {}" + joinPoint.getSignature().getName());

            throw e;
        }
    }
}