[AOP] JoinPoint 와 바인드 변수

배세훈·2022년 1월 6일
0

Spring

목록 보기
29/38

스프링 JoinPoint 에서 제공하는 메소드들

Signature getSignature()

  • 클라이언트가 호출한 메소드의 시그니처 (리턴타입, 이름, 매개변수) 정보가 저장된 Signature 객체를 리턴

Object getTarget()

  • 클라이언트가 호출한 비즈니스 메소드를 포함하는 비즈니스 객체를 리턴(해당 클래스 객체를 리턴)

Object[] getArgs()

  • 클라이언트가 메소드를 호출할 때 넘겨준 인자 목록을 Object 배열로 리턴

Around 어드바이스 메소드를 구현할 때 사용하는 ProceedingJoinPoint 인터페이스는 JoinPoint를 상속받은 클래스이다.
따라서 JoinPoint가 갖고있는 모든 메소드를 지원하며 추가적으로 proceed() 메소드가 더해진 셈이다.

주의할점은 Befor, After Returning, After Throwing, After 어드바이스를 JoinPoint를 매개변수로 사용하고, Around 어드바이스에서만 ProceedingJoinPoint를 매개변수로 사용한다는 점. Around 어드바이스에서만 proceed() 메소드가 필요하기 때문이다.

Signature 객체가 제공하는 메소드들

String getName()

  • 클라이언트가 호출한 메소드 이름 리턴

String toLongString()

  • 클라이언트가 호출한 메소드의 리턴타입, 이름, 매개변수를 패키지 경로까지 포함해서 리턴
String toShortString()
  • 클라이언트가 호출한 메소드의 시그니처를 축약한 문자열로 리턴

1. Before 어드바이스

@Before("cut() && enableDecode()")
    public void before(JoinPoint joinPoint) throws UnsupportedEncodingException{

        Object[] args = joinPoint.getArgs();
        String methodName = joinPoint.getSignature().getName();

        for(Object arg : args){
            if(arg instanceof User){
                User user = User.class.cast(arg);
                String base64Email = user.getEmail();
                String email = new String(Base64.getDecoder().decode(base64Email), "UTF-8");
                user.setEmail(email);
            }
        }

        System.out.println("실행된 메소드명: " + methodName);

    }

2. AfterReturning 어드바이스

@AfterReturning(value = "pointcut() && enableDecode()", returning = "returnObj")
    public void afterReturn(JoinPoint joinPoint, Object returnObj){
        if(returnObj instanceof User){
            User user = User.class.cast(returnObj);
            String email = user.getEmail();
            String base64Email = Base64.getEncoder().encodeToString(email.getBytes());
            user.setEmail(base64Email);
        }
    }
  • 2번째 매개변수로 Object 타입의 returnObj가 선언되어 있는데 바인드변수 이다.
    바인드변수는 비즈니스 메소드가 리턴한 결과값을 바인딩할 목적으로 사용하며, 어떤 값이 리턴될지 모르기 때문에 타입은 Object로 선언해주는 것이다.

  • @AfterReturning 안의 returning값에는 2번째 파라미터명과 일치시킨다.

3. After Throwing 어드바이스

@AfterThrowing(value = "pointcut() && enableDecode()", throwing = "exceptObj")
    public void afterThrowing(JoinPoint joinPoint, Exception exceptObj){

        String method = joinPoint.getSignature().getName();
        String errMsg = exceptObj.getMessage();

        System.out.println("메소드명: " + method);
        System.out.println("ErrMsg: " + errMsg);

    }
  • 2번째 매개변수는 Exception 정보를 가져옴
  • @AfterThrowing 안의 throwing 값에는 2번째 파라미터명과 일치시킨다.

Around 어드바이스

@Around("pointcut() && enableDecode()")
    public Object around(ProceedingJoinPoint joinPoint){
        String method = joinPoint.getSignature().getName();

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        System.out.println("around 시작");
        
        Object obj = joinPoint.proceed();
        
        stopWatch.stop();
        System.out.println("around 메소드명: " + method + "수행에 걸린 시간: " + stopWatch.getTotalTimeMillis() + "(ms)초");
        
        return obj;
    }
profile
성장형 인간

0개의 댓글