web-dev-qa-db-ja.com

javaにAnnotation Inheritanceのようなものはありますか?

私は注釈を探っていますが、いくつかの注釈にはそれらの間に階層があるように見えるようになりました。

カードのバックグラウンドでコードを生成するために注釈を使用しています。カードにはさまざまな種類があります(したがって、異なるコードと注釈)が、名前のように共通する特定の要素があります。

@Target(value = {ElementType.TYPE})
public @interface Move extends Page{
 String method1();
 String method2();
}

そして、これは一般的な注釈になります:

@Target(value = {ElementType.TYPE})
public @interface Page{
 String method3();
}

上記の例では、Moveがmethod3を継承することを期待していますが、extensionsは注釈では無効であるという警告が表示されます。私はアノテーションが共通のベースを拡張しようとしましたが、それは機能しません。それは可能ですか、それとも設計上の問題ですか?

101
javydreamercsw

残念だけど違う。どうやら、クラスの注釈をすべて読み込まずに読み込むプログラムと関係があるようです。 Javaで注釈を拡張できないのはなぜですか? を参照してください

ただし、型がスーパークラスの注釈を継承するのは、それらの注釈が @Inherited の場合です。

また、これらのメソッドが対話する必要がない限り、クラスに注釈をスタックするだけで済みます。

@Move
@Page
public class myAwesomeClass {}

うまくいかない理由はありますか?

67
andronikus

継承の代わりにベース注釈を使用して注釈に注釈を付けることができます。これは Springフレームワークで使用 です。

例を挙げます

@Target(value = {ElementType.ANNOTATION_TYPE})
public @interface Vehicle {
}

@Target(value = {ElementType.TYPE})
@Vehicle
public @interface Car {
}

@Car
class Foo {
}

次に、 SpringのAnnotationUtils を使用して、クラスにVehicleアノテーションが付けられているかどうかを確認できます。

Vehicle vehicleAnnotation = AnnotationUtils.findAnnotation (Foo.class, Vehicle.class);
boolean isAnnotated = vehicleAnnotation != null;

このメソッドは次のように実装されます。

public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
    return findAnnotation(clazz, annotationType, new HashSet<Annotation>());
}

@SuppressWarnings("unchecked")
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
    try {
        Annotation[] anns = clazz.getDeclaredAnnotations();
        for (Annotation ann : anns) {
            if (ann.annotationType() == annotationType) {
                return (A) ann;
            }
        }
        for (Annotation ann : anns) {
            if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) {
                A annotation = findAnnotation(ann.annotationType(), annotationType, visited);
                if (annotation != null) {
                    return annotation;
                }
            }
        }
    }
    catch (Exception ex) {
        handleIntrospectionFailure(clazz, ex);
        return null;
    }

    for (Class<?> ifc : clazz.getInterfaces()) {
        A annotation = findAnnotation(ifc, annotationType, visited);
        if (annotation != null) {
            return annotation;
        }
    }

    Class<?> superclass = clazz.getSuperclass();
    if (superclass == null || Object.class == superclass) {
        return null;
    }
    return findAnnotation(superclass, annotationType, visited);
}

AnnotationUtilsには、メソッドおよびその他の注釈付き要素の注釈を検索するための追加メソッドも含まれています。また、Springクラスは、ブリッジメソッド、プロキシ、およびその他のコーナーケース(特にSpringで発生するもの)を検索するのに十分強力です。

54

Grygoriysの注釈に注釈を付けることに加えて。

確認できますこのループで@Qualifierアノテーション(または@Qualifierアノテーションが付けられたアノテーション)を含めるためのメソッド:

for (Annotation a : method.getAnnotations()) {
    if (a.annotationType().isAnnotationPresent(Qualifier.class)) {
        System.out.println("found @Qualifier annotation");//found annotation having Qualifier annotation itself
    }
}

基本的にやっているのは、メソッドに存在するすべての注釈を取得し、それらの注釈の型を取得し、@ Qualifierで注釈が付けられている場合はそれらの型をチェックすることです。これを機能させるには、アノテーションもTarget.Annotation_typeを有効にする必要があります。

5
philnate