2 つのカスタム注釈がありますが、一方は常に他方より先に実行する必要があります。どうすればこれを保証できますか? ある種の順序付けはありますか、それとも追加のメソッド定義で行いますか?
7 に答える
@Order アノテーションを使用して、カスタム アノテーションの順序を確認できます。
例:
最初の注釈:
@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
}
}
2 番目の注釈:
@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 が最初に実行されます。
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-ataspectj-advice-orderingから
Spring AOP は、AspectJ と同じ優先順位規則に従って、アドバイスの実行順序を決定します。最も優先順位の高いアドバイスが「途中で」最初に実行されます (したがって、2 つの事前アドバイスが与えられた場合、最も優先順位の高いアドバイスが最初に実行されます)。結合点からの「途中」では、最も優先順位の高いアドバイスが最後に実行されます (したがって、2 つのアフター アドバイスが与えられた場合、最も優先順位の高いアドバイスが 2 番目に実行されます)。
異なる側面で定義された 2 つのアドバイスを両方とも同じ結合ポイントで実行する必要がある場合、特に指定しない限り、実行の順序は未定義です。優先順位を指定することで、実行順序を制御できます。これは、アスペクト クラスに org.springframework.core.Ordered インターフェースを実装するか、 Order アノテーションでアノテーションを付けることにより、通常の Spring の方法で行われます。2 つの側面がある場合、Ordered.getValue() (またはアノテーション値) から低い値を返す側面が優先されます。
同じアスペクトで定義された 2 つのアドバイスを同じジョイン ポイントで実行する必要がある場合、順序は未定義です (javac でコンパイルされたクラスのリフレクションを介して宣言順序を取得する方法がないため)。このようなアドバイス メソッドを、各アスペクト クラスのジョイン ポイントごとに 1 つのアドバイス メソッドにまとめるか、アドバイスの断片を個別のアスペクト クラスにリファクタリングすることを検討してください (アスペクト レベルで順序付けできます)。
チェックアウトhttps://stackoverflow.com/a/30222541/810109 : 少なくとも Java 8 では、保証された順序で注釈を取得できるため、正しい順序で宣言するだけです。
これは、EJB インターセプターを使用して実行できます。
@Interceptors( { MyInterceptor.class } ) を介してインターセプターを追加し、2 つ目の @MyInterceptorConfiguration(value=something) を追加するだけです。
bkail がここの回答で述べているように:
これは、EE 6 (EJB 3.1) の CDI ステレオタイプ アノテーション (例については、インターセプター バインディングのページを参照) でのみ可能です。
最初の注釈:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FirstAnnotation {
String value() default "";
}
2 番目の注釈:
@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'
はい、アノテーション自体が@First、@Secondなどのアノテーションを提供していると思いますので、それを試すことができます