복붙노트

[SPRING] Spring AspectJ, 메소드 OR 클래스가 주석 처리 된 메소드 실행 전에 pointcut

SPRING

Spring AspectJ, 메소드 OR 클래스가 주석 처리 된 메소드 실행 전에 pointcut

주석이 클래스 또는 메소드에있을 수있는 Spring Aop AspectJ 스타일을 통해 주석의 가치를 얻으려고합니다. 나는 많은 다른 것들을 시도했지만 주석이 메서드에있을 때만 작동하도록 할 수 있습니다. 한 번 클래스에 주석을 달고 클래스의 모든 메소드에 조언을하고 조언의 클래스 주석 값에 액세스하고 싶습니다. 내가 여기까지 왔어.

주석:

@Inherited
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "";
}

양상:

@Aspect
public class MyAspect {
    @Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
    public void atExecution() { }

    @Before("atExecution() && @annotation(myAnnotation)")
    public void myAdvice(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        ...
    }
}

이견있는 사람? 감사.

해결법

  1. ==============================

    1.직접적으로 주석이 달린 메소드와 주석이 달린 타입의 메소드 모두와 동시에 일치하는 pointcut을 공식화 할 수 있지만, 주석의 값을 바인딩 할 때 pointcut 및 / 또는 advice를 만들 수 없습니다 (예 : advice 코드의 주석 값을 사용하십시오 ).

    직접적으로 주석이 달린 메소드와 주석이 달린 타입의 메소드 모두와 동시에 일치하는 pointcut을 공식화 할 수 있지만, 주석의 값을 바인딩 할 때 pointcut 및 / 또는 advice를 만들 수 없습니다 (예 : advice 코드의 주석 값을 사용하십시오 ).

    @Aspect
    public class MyAspect {
    
        @Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
        public void atExecutionOfAnnotatedMethod() {}
    
        @Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
        public void atExecutionOfMethodsOfAnnotatedClass() {}
    
        @Before("atExecutionOfAnnotatedMethod() && @annotation(myAnnotation)")
        public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
            System.out.println("myAdviceForMethodAnnotation: " + myAnnotation.value());
        }
    
        @Before("atExecutionOfMethodsOfAnnotatedClass() && @this(myAnnotation)")
        public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
            System.out.println("myAdviceForTypeAnnotation: " + myAnnotation.value());
        }
    
        //      /* the following pointcut will result in "inconsistent binding" errors */
        //      @Pointcut("(atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)) || (atExecutionOfMethodsOfAnnotatedClass() && @this(myTypeAnnotation))")
        //      public void combinedPointcut(MyAnnotation myMethodAnnotation, MyAnnotation myTypeAnnotation) {}
    
    }
    

    두 개의 개별 pointcut (atExecutionOfAnnotatedMethod와 atExecutionOfMethodsOfAnnotatedClass)을 결합하려면 OR (||) 구조를 사용해야합니다. OR 구조는 두 주석 바인딩 중 하나가 조언 실행시 존재한다는 것을 보장하지 않기 때문에 컴파일 오류가 발생합니다 (일관성없는 바인딩). 두 가지 경우를 별도의 조언으로 처리 할 수 ​​있습니다. 중복을 피하기 위해 실제 조언 코드를 일반적인 방법으로 위임 할 수도 있습니다. 이 경우 유형과 메소드 모두 @MyAnnotation으로 주석 처리되는 경우를 처리해야합니다. 두 개의 pointcut이 모두 일치하므로 두 가지 권고에 의해 메소드가 이중으로 권고 될 것이기 때문에 일반적인 조언 처리 코드는 두 번 실행하십시오.

    두 가지 경우를 결합하여 목표 코드에 대한 조언을 두 배로하지 말고 방어해야하는 경우 메소드 수준 주석과 클래스 수준 주석 사이에 우선 순위를 설정해야합니다. 구체성의 원칙에 따라 메소드 수준의 주석이 클래스 수준의 우선 순위보다 우선 순위가 높은 경로로 이동하는 것이 좋습니다. 귀하의 측면은 다음과 같습니다.

    @Aspect
    public class MyCombinedAspect {
    
        @Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
        public void atExecutionOfAnnotatedMethod() {}
    
        @Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
        public void atExecutionOfMethodsOfAnnotatedClass() {}
    
        @Before("atExecutionOfAnnotatedMethod() && !atExecutionOfMethodsOfAnnotatedClass() && @annotation(myAnnotation)")
        public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
            handleBeforeExecution(joinPoint, myAnnotation);
        }
    
        @Before("atExecutionOfMethodsOfAnnotatedClass() && !atExecutionOfAnnotatedMethod() && @this(myAnnotation)")
        public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
            handleBeforeExecution(joinPoint, myAnnotation);
        }
    
        @Before("atExecutionOfMethodsOfAnnotatedClass() && atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)")
        public void myAdviceForDoublyAnnotated(JoinPoint joinPoint, MyAnnotation myMethodAnnotation) {
            handleBeforeExecution(joinPoint, myMethodAnnotation);
        }
    
        protected void handleBeforeExecution(JoinPoint joinPoint, MyAnnotation myAnnotation) {
            System.out.println(myAnnotation.value());
        }
    
  2. from https://stackoverflow.com/questions/34290131/spring-aspectj-pointcut-before-method-execution-where-method-or-class-is-annota by cc-by-sa and MIT license