복붙노트

[SPRING] '중첩 된'주석을위한 Spring AOP point cut

SPRING

'중첩 된'주석을위한 Spring AOP point cut

커스텀 어노테이션으로 주석 처리 된 스프링 서비스의 모든 메소드에서 실행을 트리거하는 포인트 컷을 정의해야합니다. 포인트 컷을 정의하고자하는 주석은 다른 주석에 있습니다.

@Y
public @interface X {
}

서비스는 다음과 같이 주석을 달았습니다.

@X
public Service1 {
} 

다음 포인트 컷 정의로 시도했지만 @Y가 서비스 자체에있을 때만 작동합니다. 즉 주석이 @X에 있음을 알지 못합니다.

@Around("@within(com.mypackage.Y)")

해결법

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

    1.이것은 Spring이나 AspectJ 문제가 아니다. Java에서 인터페이스, 다른 주석 또는 메서드에 대한 주석은 클래스, 주석이 달린 주석을 사용하는 클래스 또는 메서드 재정의를 통해 상속되지 않습니다. 어노테이션 상속은 클래스에서 서브 클래스로만 작동하지만, 수퍼 클래스에서 사용 된 어노테이션 유형이 메타 어노테이션 @Inherited을 지닌 경우에만 가능합니다.

    이것은 Spring이나 AspectJ 문제가 아니다. Java에서 인터페이스, 다른 주석 또는 메서드에 대한 주석은 클래스, 주석이 달린 주석을 사용하는 클래스 또는 메서드 재정의를 통해 상속되지 않습니다. 어노테이션 상속은 클래스에서 서브 클래스로만 작동하지만, 수퍼 클래스에서 사용 된 어노테이션 유형이 메타 어노테이션 @Inherited을 지닌 경우에만 가능합니다.

    업데이트 : 이전에이 질문에 여러 번 대답했기 때문에 AspectJ를 사용하여 인터페이스 및 메서드를 에뮬레이션 주석 상속에서 문제 및 해결 방법을 문서화했습니다.

    여기에 당신이 원하는 것이 작동하지 않으며 따라서 한 측면에서 활용 될 수 없다는 작은 증거가 있습니다.

    package de.scrum_master.app;
    
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    public @interface OuterAnnotation {}
    
    package de.scrum_master.app;
    
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @OuterAnnotation
    public @interface InnerAnnotation {}
    
    package de.scrum_master.app;
    
    import java.lang.annotation.Annotation;
    
    @InnerAnnotation
    public class Application {
        public static void main(String[] args) {
            for (Annotation annotation : Application.class.getAnnotations())
                System.out.println(annotation);
        }
    }
    

    콘솔 출력은 내부 주석에 사용 된 외부 주석이 아니라 JVM에 의해 내부 주석 만 표시된다는 것을 보여줍니다.

    @de.scrum_master.app.InnerAnnotation()
    

    업데이트 : 브래들리 남 핸디 (Bradley M Handy 's)의 대답에 흥미를 느끼고, 코드에 설명 된 상황에서도 작동하는지 다시 한 번 확인했습니다. 이 AspectJ 구문은 AspectJ에 대해 많은 것을 알고 있다고해도 알지 못했다. 고마워, 브래들리. :-)이 부분은 작동합니다.

    package de.scrum_master.aspect;
    
    import de.scrum_master.app.OuterAnnotation;
    
    public aspect MetaAnnotationAspect {
      after() : within(@(@OuterAnnotation *) *) && execution(* *(..)) {
        System.out.println(thisJoinPoint);
      }
    }
    

    응용 프로그램을 실행할 때 콘솔 로그 :

    @de.scrum_master.app.InnerAnnotation()
    execution(void de.scrum_master.app.Application.main(String[]))
    
  2. ==============================

    2.나는이 정확한 필요를 응용 프로그램에 가지고있었습니다. 이 답변을 찾았지만 만족스럽지 못했습니다.

    나는이 정확한 필요를 응용 프로그램에 가지고있었습니다. 이 답변을 찾았지만 만족스럽지 못했습니다.

    조금 더 검색 한 후에 AspectJ / Spring pointcut 표현을위한이 치트 시트를 발견했다. 치트 시트의 솔루션은 광고 된 것과 똑같은 방식으로 작동하지 않았지만 필자가 필요로하는 기능을 수행 할 수있었습니다.

    @Pointcut("within(@(@Annotation *) *)")
    public void classAnnotatedWithNestedAnnotationOneLevelDeep() { }
    

    이 표현식을 @Annotation에 대한 @within 표현식과 결합하여 제가 일하고 싶은 것을 얻었습니다.

    메소드 실행 :

    @Pointcut("execution(@(@com.someorg.SomeAnnotation *) * *(..))")
    public void methodAnnotatedWithNestedAnnotationOneLevelDeep() { }
    

    이 표현식을 @Annotation에 대한 @ 주석 표현식과 결합하여 메소드에 대해 작업하고 싶은 것을 얻었습니다.

  3. from https://stackoverflow.com/questions/31440131/spring-aop-point-cut-for-nested-annotation by cc-by-sa and MIT license