728x90

이와 같이 패키지 전체를 포인트 컷으로 잡아서 구현한 AOP를 Custom AOP로 바꾸어보았습니다.  

@Aspect
@Component
public class LogAspect {
    private static final Loggerlogger= LoggerFactory.getLogger(LogAspect.class);

    @Around("within(com.myproject.doseoro..*)")
    public Object logging(ProceedingJoinPoint pjp) throws Throwable {

        String params = getRequestParams();

        long startAt = System.currentTimeMillis();

logger.info("----------> REQUEST : {}({}) = {}", pjp.getSignature().getDeclaringTypeName(),
                pjp.getSignature().getName(), params);

        Object result = pjp.proceed();

        long endAt = System.currentTimeMillis();

logger.info("----------> RESPONSE : {}({}) = {} ({}ms)", pjp.getSignature().getDeclaringTypeName(),
                pjp.getSignature().getName(), result, endAt-startAt);

        return result;
    }

    private String getRequestParams() {

        String params = "";

        RequestAttributes requestAttribute = RequestContextHolder.getRequestAttributes();

        if (requestAttribute != null) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes()).getRequest();

            Map<String, String[]> paramMap = request.getParameterMap();

            if (!paramMap.isEmpty()) {
                params = " [" + paramMapToString(paramMap) + "]";
            }
        }
        return params;
    }

    private String paramMapToString(Map<String, String[]> paramMap) {
        StringJoiner sj = new StringJoiner(",", "[", "]");
        return paramMap.entrySet().stream()
                .map(entry -> String.format("$s -> ($s)",
                        entry.getKey(), sj,join(entry.getValue())))
                .collect(Collectors.joining(", "));
    }
}

 

바꾼 이유는 공부 목적도 있었고 멘토님이 말하시길 "코드상 눈에 보이는 표식을 하지 않았기 때문에 모르는 사람이 볼때는 Aspect 로직이 왜 실행되는지 이해를 하지 못하는 경우도 많다"고 하셨다. 듣고 보니 정말 그럴 것 같았다.

 

어떻게 바뀌었냐면 

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Logging {}
@Aspect
@Component
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Around("@annotation(Logging)") // Custom AOP
    public Object logging(ProceedingJoinPoint pjp) throws Throwable {
    
    	// ... 이하 위 로직과 같음

 

이렇게 바꿈으로써 전에 없었던 어노테이션이 생겼고, 그 어노테이션으로 무엇을 하려고 하는지 정확히 알 수 있었습니다.

 

 

이 과정에서 @Transactional, @Cacheable, @Async 에너테이션도 AOP가 적용된 사례라는 것을 알게되었습니다.

 

 

참고

https://velog.io/@ann0905/AOP%EC%99%80-Transactional%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC

 

AOP와 @Transactional의 동작 원리

오늘은 @Transactional의 동작 원리를 AOP와 함께 좀 더 자세하게 조사해보려고 한다.여기서 다루는 내용은 다음과 같다.AOP란 무엇이며 왜 사용하는가Spring AOP는 왜 프록시를 사용하는가@Transactional은

velog.io

https://tecoble.techcourse.co.kr/post/2021-06-25-aop-transaction/

 

AOP 입문자를 위한 개념 이해하기

이 글은 AOP 개념이 생소한 입문자들을 위한 포스팅입니다. 1. OOP의 한계 image…

tecoble.techcourse.co.kr

https://private-space.tistory.com/98

 

Spring에서 AOP를 구현하는 방법과 Transactional

Spring에서 AOP를 구현하는 방법과 Transactional AOP에 관한 간략한 개념이 필요하다면 다른 글을 참조한다. 이 내용은 공식 문서를 참조하여 작성하였다. Spring Framework Document AOP 구현 방식 Spring에서 A..

private-space.tistory.com

 

+ Recent posts