복붙노트

[SPRING] 주석이 달린 매개 변수를 기반으로 Aspect 포인트 컷을 작성하는 방법

SPRING

주석이 달린 매개 변수를 기반으로 Aspect 포인트 컷을 작성하는 방법

주석이 달린 특정 매개 변수가있는 bean에서 작동하는 pointcut을 만드는 방법을 해결하는 데 약간의 어려움이 있습니다. 최종 목표는 처리되기 전에 매개 변수의 값을 확인하는 것이지만 현재는 포인트 컷을 만들어야합니다.

다음 주석을 고려하십시오

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER })
public @interface MyAnnotation {}

그런 다음 이것을 다음과 같은 여러 가지 방법에 적용하고 싶습니다.

public void method1(@MyAnnotation long i) {}
public void method2(String someThing, @MyAnnotation long i) {}
public void method3(String someThing, @MyAnnotation long i, byte value) {}

그래서

내 pointcut 구현은 다음 라인을 따라야합니다.

@Before(value = "* *(..) && args(verifyMe)")
public void verifyInvestigationId(long verifyMe) {}

@Before 값이 무엇이고 주석과 유형을 연결하는 방법에 대해 약간 혼란 스럽습니다. 이 시점에서 내가 시도한 것들을 나열 할 가치가 없을 것입니다!

업데이트 : http://stackoverflow.com/questions/3565718/pointcut-matching-methods-with-annotated-parameters/3567170#3567170에서 보았던 조언을 바탕으로 (그리고 몇 가지 오해를 수정하고 간과 한 공간을 추가했습니다. ) 나는 다음이 작동하는 시점에 도달했다.

@Before("execution(public * *(.., @full.path.to.MyAnnotation (*), ..))")
public void beforeMethod(JoinPoint joinPoint) {
    System.out.println("At least one of the parameters are annotated with @MyAnnotation");
}

이것은 거의 내가 필요한 것입니다-주석이 달린 인수의 값을 매개 변수로 메소드에 전달하기 만하면됩니다. Spring 이이 작업을 수행하도록 구문을 해결할 수는 없습니다 (링크 된 답변에는 표시되지 않음).

해결법

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

    1.sheltem이 이미 지적한 내 대답과 매우 유사하게 솔루션은 다음과 같습니다 (이번 주석 스타일 구문에서는 Spring AOP에서는 기본 AspectJ 구문을 사용할 수 없기 때문에).

    sheltem이 이미 지적한 내 대답과 매우 유사하게 솔루션은 다음과 같습니다 (이번 주석 스타일 구문에서는 Spring AOP에서는 기본 AspectJ 구문을 사용할 수 없기 때문에).

    원본 포스터 주석 :

    package annotations;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.PARAMETER })
    public @interface MyAnnotation {}
    

    운전사 신청 :

    AspectJ 솔루션을 테스트하기 위해 드라이버 응용 프로그램을 사용합니다. Spring에서는 클래스뿐만 아니라 aspect도 스프링 빈 / 컴포넌트 여야합니다.

    package de.scrum_master.app;
    
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import annotations.MyAnnotation;
    
    public class Application {
        public void method1(@MyAnnotation int i) {}
        public void method2(String id, @MyAnnotation float f) {}
        public void method3(int i, @MyAnnotation List<String> strings, @MyAnnotation String s) {}
        public void method4(int i, @MyAnnotation Set<Integer> numbers, float f, boolean b) {}
        public void method5(boolean b, String s, @MyAnnotation String s2, float f, int i) {}
        public void notIntercepted(boolean b, String s, String s2, float f, int i) {}
    
        public static void main(String[] args) {
            List<String> strings = new ArrayList<String>();
            strings.add("foo");
            strings.add("bar");
            Set<Integer> numbers = new HashSet<Integer>();
            numbers.add(11);
            numbers.add(22);
            numbers.add(33);
    
            Application app = new Application();
            app.method1(1);
            app.method2("foo", 1f);
            app.method3(1, strings, "foo");
            app.method4(1, numbers, 1f, true);
            app.method5(false, "foo", "bar", 1f, 1);
            app.notIntercepted(false, "foo", "bar", 1f, 1);
        }
    }
    

    양상:

    package de.scrum_master.aspect;
    
    import java.lang.annotation.Annotation;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.SoftException;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.reflect.MethodSignature;
    
    import annotations.MyAnnotation;
    
    @Aspect
    public class ArgCatcherAspect {
        @Before("execution(public * *(.., @MyAnnotation (*), ..))")
        public void interceptMethodsWithAnnotatedParameters(JoinPoint thisJoinPoint) {
            System.out.println(thisJoinPoint);
            MethodSignature signature = (MethodSignature) thisJoinPoint.getSignature();
            String methodName = signature.getMethod().getName();
            Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
            Annotation[][] annotations;
            try {
                annotations = thisJoinPoint.getTarget().getClass().
                    getMethod(methodName, parameterTypes).getParameterAnnotations();
            } catch (Exception e) {
                throw new SoftException(e);
            }
            int i = 0;
            for (Object arg : thisJoinPoint.getArgs()) {
                for (Annotation annotation : annotations[i]) {
                    if (annotation.annotationType() == MyAnnotation.class) {
                        System.out.println("  " + annotation + " -> " + arg);
                        // Verify 'arg' here or do whatever
                    }
                }
                i++;
            }
        }
    }
    

    콘솔 로그 :

    execution(void de.scrum_master.app.Application.method1(int))
      @annotations.MyAnnotation() -> 1
    execution(void de.scrum_master.app.Application.method2(String, float))
      @annotations.MyAnnotation() -> 1.0
    execution(void de.scrum_master.app.Application.method3(int, List, String))
      @annotations.MyAnnotation() -> [foo, bar]
      @annotations.MyAnnotation() -> foo
    execution(void de.scrum_master.app.Application.method4(int, Set, float, boolean))
      @annotations.MyAnnotation() -> [33, 22, 11]
    execution(void de.scrum_master.app.Application.method5(boolean, String, String, float, int))
      @annotations.MyAnnotation() -> bar
    
  2. ==============================

    2.이것은 내가 그것에 대해 고민 한 후에 끝났습니다 (수입 생략).

    이것은 내가 그것에 대해 고민 한 후에 끝났습니다 (수입 생략).

    @Aspect
    public class VerifyAspect {
    
        @Before("execution(* *(.., @annotations.MyAnnotation (*), ..)) && args(.., verifyMe)")
        public void verifyInvestigationId(final Object verifyMe) {
            System.out.println("Aspect verifying: " + verifyMe);
        }
    }
    

    AspectJ는 이미 원하는 경우 매개 변수를 이미 제공하므로 Spring에 필요한 것은 없습니다.

  3. from https://stackoverflow.com/questions/29681675/how-to-write-an-aspect-pointcut-based-on-an-annotated-parameter by cc-by-sa and MIT license