2023.04.03 AOP에 대한 작은 실험?

서승원·2023년 4월 3일
0
post-thumbnail

문제

  • AOP를 이용해서 custom annotation으로 권한 처리 로직을 개발중에 advice 클래스에서 @Around 조건을 수정 중 처음 보는 유형으로 boot에 실패했다.
@Around(value = "@annotation(firstMethod) || @annotation(secondMethod)",
	argNames = "joinPoint,firstMethod,secondMethod")
    public Object SomethingAnnotated(ProceedingJoinPoint joinPoint, 
    	FirstMethod firstMethod, SecondMethod secondMethod) throws Throwable {
        return joinPoint.proceed();
    }
Error creating bean with name 'org.springframework.boot.autoconfigure.web.
servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat'
: error at ::0 inconsistent binding
  • 서치 결과 inconsistent binding 즉, 일관성 없는 binding
  • stackoverflow의 한 유저 에 따르면 || (OR연산자) 의 모호한 condition 때문에 argument로 사용되는 두 어노테이션 중 어떤 어노테이션이 바인딩 될지 불확실해서 BeanCreationException 이 발생했다.

궁금증

  • 그러면, 모호하지 않도록 @First && @Second , @First && !@Second, !@First && @Second 을 경우에 따라 지정하면 될까?
  • 그렇다면 @First && @Second 면 두 어노테이션 모두 잘 binding 될까?
  1. 모두 바인딩 해보기
@Around(value = "firstAnnotated(firstMethod) &&
	!secondAnnotated(secondMethod)", argNames = "joinPoint,firstMethod,secondMethod")
negation doesn't allow binding

부정형은 바인딩이 불가능..

  1. argument 로 사용하지 않기
@Aspect
@Component
@Slf4j
public class SampleAspect {
    @Pointcut("@annotation(com.example.aoppractice.annotation.FirstMethod)")
    public void firstAnnotated(){}
    @Pointcut("@annotation(com.example.aoppractice.annotation.SecondMethod)")
    public void secondAnnotated(){}

    @Around(value = "firstAnnotated() || secondAnnotated()")
    public Object BothAnnotated(ProceedingJoinPoint joinPoint) throws Throwable {
        return joinPoint.proceed();
    }
}

어플리케이션 부팅까지 성공했다. 이제 문제는 annotation 사용하기

    @Around(value = "firstAnnotated() || secondAnnotated()")
    public Object BothAnnotated(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        FirstMethod firstMethod = method.getAnnotation(FirstMethod.class);
        SecondMethod secondMethod = method.getAnnotation(SecondMethod.class);
        log.info(firstMethod.toString());
        log.info(secondMethod.toString());
        return joinPoint.proceed();
    }
  • HelloController.java
    @GetMapping("/first")
    public void first() {
        helloService.first();
    }
    @GetMapping("/second")
    public void second() {
        helloService.second();
    }
    @GetMapping("/both")
    public void both() {
        helloService.both();
    }

이 세가지 API를 통해 실험해봤을 때, both에서는 문제가 발생하지 않았는데 first, second 에서는 toString() 을 호출하며 NullPointerException이 발생했다.

아무래도 OR 조건으로 Around 를 사용하려면 이렇게 직접 getAnnotation()을 호출해야 할 것 같다.
Null값에 대한 방어가 관건이겠다.

reference

https://stackoverflow.com/questions/43331538/aop-error-at-0-inconsistent-binding-applying-aop-on-two-different-methods

profile
2년차 백엔드 개발자, crimy

0개의 댓글