2013-01-14 137 views
7

我有2個自定義註釋,但一個應該總是在另一個之前執行。我如何確保這一點?是否有某種排序或使用附加的方法定義進行排序?如何確保java中的註釋執行順序?

+1

最新情況?隨機工作? – vels4j

+0

或按字母順序? –

+0

看來,'Class'中的註釋描述存儲在'HashMap'中。當然,這並不能保證本機的順序。所以,我認爲,沒有辦法。 – Andremoniy

回答

-1

是的,我覺得詮釋本身提供了註解,像@First和@Second等,所以你可以嘗試

+5

你這麼認爲,或者你檢查過嗎? :) – Andremoniy

0

您可以通過使用EJB攔截做到這一點。

您可以通過@Interceptors({MyInterceptor.class})簡單地添加攔截器,然後添加第二個@MyInterceptorConfiguration(value = something)。

正如bkail說,在their answer here

這是唯一可能與CDI刻板印象 註釋(參見例如攔截 綁定頁)EE 6(EJB 3.1)。

+0

我使用彈簧:) – user358448

+0

這可能會幫助你,http://docs.oracle.com/javase/1.5.0/docs/guide/apt/index.html代碼適合註釋。 – Amol

+0

我不明白這一點。 – user358448

-1

首先註解:

@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' 
0

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-ataspectj-advice-ordering

的Spring AOP遵循相同的優先級規則的AspectJ來確定通知執行的順序。最高優先級建議首先「在途中」運行(因此給定兩條先前的建議,最高優先級的建議先運行)。從連接點出來的「出路」中,最高優先級通知最後運行(因此給定兩條通知後,優先級最高的通道將運行第二條通道)。

當在不同方面定義的兩條建議都需要在同一個連接點上運行時,除非您另行指定,否則執行順序未定義。您可以通過指定優先級來控制執行順序。這是以普通的Spring方式完成的,方法是在aspect類中實現org.springframework.core.Ordered接口或使用Order註釋對其進行註釋。給定兩個方面,從Ordered.getValue()(或註釋值)返回較低值的方面具有較高的優先級。

當同一方面定義的兩條建議都需要在同一個連接點上運行時,排序是未定義的(因爲沒有辦法通過反射爲javac編譯的類檢索聲明順序)。考慮將這些通知方法分解爲每個方面類中每個連接點的一個通知方法,或者將通知重構爲單獨的方面類 - 可以在方面級別進行排序。

4

您可以使用@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將首先執行。

+0

請添加一個簡單的例子,而不僅僅是一個鏈接,因爲它可能會在未來 –

+0

我添加了一個例子。 – Roman

1

我知道這是一個很老的問題,但我只是想記錄我的發現。任何人都可以確認這些是否正確? 在本頁中已經提到Spring文檔說註釋的執行是未定義的,除非使用@Order註釋。 我嘗試重新命名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 

我改名註釋@A到@C,以下是日誌:

A_Aspect 
B_Aspect 

但是,當我試圖重新命名方面類A_Aspect到C_Aspect,以下是日誌:

B_Aspect 
C_Aspect 

正如我所說,我想要有人來確認這一點,因爲我找不到任何文件這