2013-01-14 4 views
7

ho 2 annotazioni personalizzate, ma una deve sempre essere eseguita prima dell'altra. Come posso assicurarlo? Esiste qualche tipo di ordinamento o lo fa con definizioni di metodo aggiuntive?Come garantire l'ordine di esecuzione delle annotazioni in java?

+1

cosa sta succedendo? funziona a caso? – vels4j

+0

Oppure in ordine alfabetico? –

+0

Sembra che le descrizioni delle annotazioni in 'Class' siano memorizzate in' HashMap'. Questo non è garanzia di ordine nativo, ovviamente. Quindi, penso, non c'è modo. – Andremoniy

risposta

-1

Sì penso annotazione si prevede di annotazione per che, come @First, e @Second ecc in modo da poter provare che

+5

Lo pensi o l'hai controllato? :) – Andremoniy

0

è possibile farlo utilizzando intercettori EJB.

è possibile aggiungere semplicemente intercettori tramite @Interceptors ({MyInterceptor.class}) e quindi aggiungere per secondo uno @MyInterceptorConfiguration (value = something).

Come bkail dice in their answer here:

Ciò è possibile solo con CDI stereotipo annotazioni (vedere pagina intercettore binding per gli esempi) a EE 6 (EJB 3.1).

+0

sto usando la molla :) – user358448

+0

Questo potrebbe aiutare, http://docs.oracle.com/javase/1.5.0/docs/guide/apt/index.html codice appropriato per l'annotazione. – Amol

+0

non capisco questo. – user358448

-1

Prima annotazione:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface FirstAnnotation { 
    String value() default ""; 
} 

Seconda annotazione: esempio

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface SecondAnnotation { 
    String value() default ""; 
} 

Usage:

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()); 

    } 

} 

Risultato/uscita:

@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

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

Spring AOP segue le stesse regole di precedenza come AspectJ per determinare l'ordine di esecuzione consigli. Il consiglio sulla precedenza più alta viene eseguito per primo "sulla strada" (quindi, dato due consigli prima, quello con la precedenza più alta viene eseguito per primo). "All'uscita" da un punto di congiunzione, il consiglio di precedenza più alto viene eseguito per ultimo (quindi, in base a due post-consigli, quello con la precedenza più alta verrà eseguito per secondo).

Quando due consigli definiti in aspetti diversi devono entrambi essere eseguiti nello stesso punto di unione, a meno che non si specifichi diversamente l'ordine di esecuzione non è definito. È possibile controllare l'ordine di esecuzione specificando la precedenza. Questo avviene nel normale modo Spring implementando l'interfaccia org.springframework.core.Ordered nella classe aspect o annotandolo con l'annotazione Order. Dati due aspetti, l'aspetto che restituisce il valore inferiore da Ordered.getValue() (o il valore di annotazione) ha la precedenza più alta.

Quando due consigli definiti nello stesso aspetto devono essere eseguiti nello stesso punto di unione, l'ordine non è definito (poiché non è possibile recuperare l'ordine di dichiarazione tramite riflessione per le classi compilate da javac). Considera la possibilità di smantellare tali metodi di consulenza in un unico metodo di consulenza per punto di unione in ciascuna classe di aspetto o di rifattorizzare i consigli in classi di aspetto separate, che possono essere ordinate a livello di aspetto.

4

È possibile garantire l'ordine delle annotazioni personalizzate con l'annotazione @ Ordine.

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/Order.html

Esempio:

Prima annotazione:

@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 
    } 
} 

Seconda annotazione:

@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 
    } 

Il loro utilizzo:

@CustomAnnotationTwo 
@CustomAnnotation 
public void someMethod(){ 
} 

In questo esempio, CustomAnnotationInterceptor verrà eseguito per primo.

+0

Si prega di aggiungere un semplice esempio di questo, non solo un collegamento in quanto potrebbe andare in futuro –

+0

Ho aggiunto un esempio. – Roman

1

So che questa è una domanda molto vecchia, ma volevo solo documentare le mie scoperte. Qualcuno può confermare se questi sono corretti? E 'già menzionato in questa pagina che la documentazione di Spring dice che l'esecuzione delle annotazioni non è definita a meno che non si usi l'annotazione @Order. Ho provato a rinominare le classi Aspect, e ho provato molte volte, e ho scoperto che le classi Aspect sono eseguite in ordine alfabetico dei loro nomi e ho trovato che il risultato è coerente.

Qui di seguito è il mio codice di esempio:

@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(){} 
} 

Quando ho provato ad eseguire advisedMethod(), che seguono sono i registri che ho ricevuto:

A_Aspect 
B_Aspect 

ho cambiato sequenza dichiarazione della nota:

@A 
@B 
public void advisedMethod(){} 

Di seguito sono riportati i registri:

A_Aspect 
B_Aspect 

ho rinominato annotazione @A a @C, seguito sono i registri:

A_Aspect 
B_Aspect 

Ma, quando ho provato a cambiare titolo di classe Aspect A_Aspect a C_Aspect, seguito sono riportati i log:

B_Aspect 
C_Aspect 

Come ho detto, voglio che qualcuno lo confermi perché non sono riuscito a trovare alcuna documentazione per questo