[SPRING] 어떻게 자바에서 주석 실행 순서를 보장하기 위해?
SPRING어떻게 자바에서 주석 실행 순서를 보장하기 위해?
2 개의 사용자 지정 주석이 있지만 항상 다른 주석보다 먼저 실행해야합니다. 어떻게해야합니까? 어떤 종류의 순서가 있나요? 아니면 추가 메서드 정의로할까요?
해결법
-
==============================
1.@Order 주석으로 맞춤 주석의 순서를 확인할 수 있습니다.
@Order 주석으로 맞춤 주석의 순서를 확인할 수 있습니다.
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/Order.html
예:
첫 번째 주석 :
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CustomAnnotation { } @Aspect @Component @Order(value = 1) public class CustomAnnotationInterceptor { @Before("@annotation(customAnnotation )") public void intercept(JoinPoint method, CustomAnnotation customAnnotation ) { //Code here } }
두 번째 주석 :
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CustomAnnotationTwo { } @Aspect @Component @Order(value = 2) public class CustomAnnotationInterceptorTwo { @Before("@annotation(customAnnotationTwo )") public void intercept(JoinPoint method, CustomAnnotationTwo customAnnotationTwo ) { //Code here }
그들을 사용 :
@CustomAnnotationTwo @CustomAnnotation public void someMethod(){ }
이 예제에서는 CustomAnnotationInterceptor가 먼저 실행됩니다.
-
==============================
2.나는 이것이 매우 오래된 질문이라는 것을 알고 있지만, 나는 단지 나의 발견을 문서화하고 싶었다. 누구나 확인할 수 있습니까? 이 페이지에서 @Order 주석이 사용되지 않는 한 주석 문서의 실행은 정의되지 않는다고 Spring 문서에서 이미 언급되었습니다. Aspect 클래스의 이름을 바꾸려고 시도하고 여러 번 테스트 한 결과 Aspect 클래스가 이름의 사전 순으로 실행되고 결과가 일관됨을 발견했습니다.
나는 이것이 매우 오래된 질문이라는 것을 알고 있지만, 나는 단지 나의 발견을 문서화하고 싶었다. 누구나 확인할 수 있습니까? 이 페이지에서 @Order 주석이 사용되지 않는 한 주석 문서의 실행은 정의되지 않는다고 Spring 문서에서 이미 언급되었습니다. Aspect 클래스의 이름을 바꾸려고 시도하고 여러 번 테스트 한 결과 Aspect 클래스가 이름의 사전 순으로 실행되고 결과가 일관됨을 발견했습니다.
아래 샘플 코드는 다음과 같습니다.
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface A {} @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface B {} @Aspect public class A_Aspect { @Around("@annotation(mypackage.A)") public void around(ProceedingJoinPoint joinPoint) { System.out.println("A_Aspect"); joinPoint.proceed(); } } @Aspect public class B_Aspect { @Around("@annotation(mypackage.B)") public void around(ProceedingJoinPoint joinPoint) { System.out.println("B_Aspect"); joinPoint.proceed(); } } class AdvisedClass{ @B @A public void advisedMethod(){} }
advisedMethod ()를 실행하려고 할 때받은 로그는 다음과 같습니다.
A_Aspect B_Aspect
주석 선언 순서를 변경했습니다.
@A @B public void advisedMethod(){}
다음은 로그입니다.
A_Aspect B_Aspect
내가 Annotation @A를 @C로 바꿨다. 다음은 로그들이다.
A_Aspect B_Aspect
하지만 Aspect 클래스 A_Aspect의 이름을 C_Aspect로 변경하려고하면 다음과 같은 로그가 표시됩니다.
B_Aspect C_Aspect
내가 말했듯이, 나는 이것에 대한 어떤 문서도 찾을 수 없었기 때문에 누군가가 이것을 확인하기를 원한다.
-
==============================
3.http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-ataspectj-advice-ordering에서
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-ataspectj-advice-ordering에서
Spring AOP는 AspectJ와 동일한 선행 규칙을 따라 advice 실행 순서를 결정한다. 우선 순위가 가장 높은 조언이 먼저 실행됩니다 (사전 조언 2 개가 주어 지므로 가장 우선 순위가 높은 조언이 먼저 실행됩니다). 조인 포인트에서 "나가는 중"에서 가장 높은 우선 순위 조언이 마지막으로 실행됩니다 (따라서 두 가지 조언이 주어지면 우선 순위가 가장 높은 조언이 두 번째 실행됩니다).
서로 다른 측면에서 정의 된 두 가지 조언이 모두 동일한 조인 포인트에서 실행되어야하는 경우 달리 지정하지 않으면 실행 순서가 정의되지 않습니다. 우선 순위를 지정하여 실행 순서를 제어 할 수 있습니다. 이는 aspect 클래스에서 org.springframework.core.Ordered 인터페이스를 구현하거나 Order 애노테이션으로 annotation함으로써 일반적인 Spring 방식으로 수행된다. 두 가지 측면에서 보면 Ordered.getValue () (또는 주석 값)에서 낮은 값을 반환하는 aspect가 더 높은 우선 순위를 갖습니다.
동일한 측면에서 정의 된 두 가지 조언이 모두 같은 조인 포인트에서 실행되어야하는 경우 순서는 정의되지 않습니다 (javac 컴파일 클래스의 리플렉션을 통해 선언 순서를 검색 할 방법이 없으므로). 이러한 애스펙트 메소드를 각 애스펙트 클래스의 조인 포인트 당 하나의 advice 메소드로 축소 시키거나 aspect의 레벨에서 정렬 할 수있는 별도의 애스펙트 클래스로 advice 조각을 리팩터링하는 것을 고려하십시오.
-
==============================
4.EJB 인터셉터를 사용하여이를 수행 할 수 있습니다.
EJB 인터셉터를 사용하여이를 수행 할 수 있습니다.
@Interceptors ({MyInterceptor.class})를 통해 인터셉터를 추가 한 다음 두 번째 @MyInterceptorConfiguration (value = something)을 추가하면됩니다.
bkail이 대답 할 때 다음과 같이 말합니다.
-
==============================
5.Checkout https://stackoverflow.com/a/30222541/810109 : 적어도 Java 8에서는 보장 된 순서로 주석을 검색 할 수 있으므로 올바른 순서로 주석을 작성해야합니다.
Checkout https://stackoverflow.com/a/30222541/810109 : 적어도 Java 8에서는 보장 된 순서로 주석을 검색 할 수 있으므로 올바른 순서로 주석을 작성해야합니다.
-
==============================
6.그렇습니다. 주석 자체는 @First, @Second 등과 같은 주석을 제공한다고 생각합니다.
그렇습니다. 주석 자체는 @First, @Second 등과 같은 주석을 제공한다고 생각합니다.
-
==============================
7.첫 번째 주석 :
첫 번째 주석 :
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface FirstAnnotation { String value() default ""; }
두 번째 주석 :
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface SecondAnnotation { String value() default ""; }
사용 예 :
public class Test { @SecondAnnotation("second annotation") @FirstAnnotation("first annotation") private String annotatedField1 = "value of field 1"; @SecondAnnotation("second annotation") @FirstAnnotation("first annotation") private String annotatedField2 = "value of field 2"; @SecondAnnotation("second annotation") private String annotatedField3 = "value of field 3"; @FirstAnnotation("first annotation") private String annotatedField4 = "value of field 4"; // Sample public static void processAnnotatedFields( final Object obj ) throws IllegalArgumentException, IllegalAccessException { for ( final Field field : getFieldsFornAnotation( obj, FirstAnnotation.class ) ) { // Do something with fields that are annotated with @FirstAnnotation final FirstAnnotation an = field.getAnnotation( FirstAnnotation.class ); System.out.print( "@" +an.annotationType().getSimpleName()+ "(" +an.value()+ "): " ); System.out.println( field.getName()+ " = '" +field.get(obj)+ "'" ); } System.out.println(); for ( final Field field : getFieldsFornAnotation( obj, SecondAnnotation.class ) ) { // Do something with fields that are annotated with @SecondAnnotation final SecondAnnotation an = field.getAnnotation( SecondAnnotation.class ); System.out.print( "@" +an.annotationType().getSimpleName()+ "(" +an.value()+ "): " ); System.out.println( field.getName()+ " = '" +field.get(obj)+ "'" ); } } /** * Collect object fields annotated with "annotationClass" * This can be saved in static map to increase performance. */ private static final Set<Field> getFieldsFornAnotation( final Object o, final Class<? extends Annotation> annotationClass ) { final Set<Field> fields = new LinkedHashSet<Field>(); if ( o == null || annotationClass == null ) return fields; for (final Field field : o.getClass().getDeclaredFields()) { if (field.isAnnotationPresent(annotationClass)) { field.setAccessible( true ); fields.add( field ); } } return fields; } public static void main(final String[] args) throws IllegalArgumentException, IllegalAccessException { processAnnotatedFields( new Test() ); } }
결과 / 출력 :
@FirstAnnotation(first annotation): annotatedField1 = 'value of field 1' @FirstAnnotation(first annotation): annotatedField2 = 'value of field 2' @FirstAnnotation(first annotation): annotatedField4 = 'value of field 4' @SecondAnnotation(second annotation): annotatedField1 = 'value of field 1' @SecondAnnotation(second annotation): annotatedField2 = 'value of field 2' @SecondAnnotation(second annotation): annotatedField3 = 'value of field 3'
from https://stackoverflow.com/questions/14318438/how-to-ensure-annotations-execution-order-in-java by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 호출되지 않는 Spring 싱글 톤 Bean의 @PreDestroy 메소드 (0) | 2019.02.14 |
---|---|
[SPRING] 봄 MVC 컨트롤러에서 컨텍스트 경로를 얻는 방법 (0) | 2019.02.14 |
[SPRING] 추상 클래스의 Spring Autowire Annotation : 고유 bean이 정의되어 있지 않다. (0) | 2019.02.14 |
[SPRING] 스프링 CSRF 토큰과 함께 Struts2에서 파일 업로드 (1) | 2019.02.14 |
[SPRING] 스프링 보안 - 액세스가 거부되었습니다 (사용자는 익명이 아닙니다) spring-security-core-4.0.3.RELEASE (0) | 2019.02.14 |