How to ensure annotation execution order in java?

I have 2 user annotations, but each should always be executed before the other. How can I guarantee this? Is there any order or do this with additional method definitions?

+7
source share
7 answers

You can keep your custom annotations in order with the @Order annotation.

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

Example:

First annotation:

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

Second annotation:

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

Using them:

 @CustomAnnotationTwo @CustomAnnotation public void someMethod(){ } 

In this example, the CustomAnnotationInterceptor will run first.

+4
source

I know this is a very old question, but I just wanted to document my findings. Can anyone confirm if they are correct? On this page, it has already been mentioned that the Spring documentation says that annotation execution is undefined if @Order annotation is not used. I tried to rename the Aspect classes and checked many times, and found that the Aspect classes are executed in alphabetical order of their names and find that the result is consistent.

The following is sample code:

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

When I tried to execute advisedMethod (), the following logs I received:

 A_Aspect B_Aspect 

I changed the annotation declaration sequence:

 @A @B public void advisedMethod(){} 

The following are the logs:

 A_Aspect B_Aspect 

I renamed @A Annotation to @C, The following are the logs:

 A_Aspect B_Aspect 

But, when I tried to rename the Aspect class A_Aspect to C_Aspect, the following logs:

 B_Aspect C_Aspect 

As I said, I want someone to confirm this, since I could not find any documentation for this

+1
source

You can do this using EJB interceptors.

you can just add interceptors via @Interceptors ({MyInterceptor.class}) and then add @MyInterceptorConfiguration (value = something) for the second.

As bkail says in their answer here :

This is only possible using the CDI annotation stereotype (see interceptor binding examples) in EE 6 (EJB 3.1).

0
source

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

Spring AOP follows the same priority rules as AspectJ to determine the order in which recommendations are followed. The council with the highest priority starts first "along the way" (so two pieces are given before the council, the first with the highest priority starts first). β€œAt the exit” from the connection point, the last tip with the highest priority works last (so two pieces are given after the consultation, the one with the highest priority will work second).

When two tips, defined in different aspects, both must be executed at the same junction, unless you specify otherwise, the order of execution is undefined. You can control the order of execution by specifying priority. This is done in the usual way of Spring by implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with an order annotation. Given two aspects, an aspect returning a lower value from Ordered.getValue () (or an annotation value) takes precedence.

When two parts of recommendations defined in the same aspect, both must be executed at the same junction point, the order is undefined (since there is no way to get the declaration order through reflection for classes compiled by javac). Consider folding these tips into one consultation method at each junction point in each aspect class or reorganizing the tips into separate aspect classes that can be ordered at the aspect level.

0
source

Place an order https://stackoverflow.com/a/168268/ At least in Java 8, you can get annotations in a guaranteed order, so you just need to declare them in the correct order.

0
source

Yes, I think the annotation itself provides an annotation for ones like @First and @Second etc., so you can try this

-one
source

First annotation:

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

Second annotation:

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

Usage example:

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

Result / Exit:

 @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' 
-one
source

All Articles