43

プロパティ付きの注釈があるとします。

@Named(name = "Steve")
private Person person

プロパティを取得するものを含め、いくつかのメタアノテーションを使用して複合アノテーションを作成したい

@Named
@AnotherAnnotation
@YetAnotherAnnotation
public @interface CompoundAnnotation {

    ...
}

複合アノテーションのプロパティをメタアノテーションの1つに渡す方法はありますか?

たとえば、次のようなものです。

@CompoundAnnotation(name = "Bob")
private Person person;

これは同等ですが、よりもはるかに便利です

@Named(name = "Bob")
@AnotherAnnotation
@YetAnotherAnnotation
private Person person;

ありがとう!

アノテーションの例を選択しなかったことをお詫びします-javax.inject。@Namedアノテーションを念頭に置いておらず、プロパティを持つ任意のアノテーションだけを考えていました。


皆様のご回答・ご感想ありがとうございました。

これが不可能なのは間違いないようです。ただし、たまたま私のケースインポイントには簡単な回避策があります。これは、誰かに役立つ場合に備えて共有します。

Springを使用していて、メタアノテーションとして@Componentを持つ独自のアノテーションを作成したいので、コンポーネントのスキャンによって自動検出されます。ただし、BeanNameプロパティ(@Componentのvalueプロパティに対応)を設定して、カスタムBean名を設定できるようにすることも必要でした。

Springの思いやりのある人たちが、まさにそれを可能にしたことがわかりました。AnnotationBeanNameGeneratorは、渡されたアノテーションの「value」プロパティを取得し、それをBean名として使用します(もちろん、デフォルトでは、 @Componentであるか、メタアノテーションとして@Componentを持つアノテーションのみが渡されます)。振り返ってみると、これは最初から私には明らかだったはずです。これは、@Serviceや@Registryなどのメタアノテーションとして@Componentを使用する既存のアノテーションがBean名を提供する方法です。

それが誰かに役立つことを願っています。それでも、これがもっと一般的に不可能なのは残念だと思います!

4

2 に答える 2

53

数年後の今、Spring を使用しているため、@AliasFor アノテーションを使用して、求めていることが可能になりました。

例えば:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration
@ActiveProfiles("test")
public @interface SpringContextTest {

    @AliasFor(annotation = SpringApplicationConfiguration.class, attribute = "classes")
    Class<?>[] value() default {};

    @AliasFor("value")
    Class<?>[] classes() default {};
}

これで、テストに で注釈を付けることができます。@SpringContextTest(MyConfig.class)驚くべきことに、それは実際に期待どおりに機能します。

注: プログラムで属性値を取得する必要がある場合、Spring の自動エイリアシングは、ドキュメントに記載されているように、AnnotatedElementUtils代わりにを使用する場合にのみ機能します。AnnotationUtils

AnnotatedElementUtilsアノテーション属性オーバーライドをサポートする Spring のメタアノテーション プログラミング モデルのパブリック API を定義します。アノテーション属性オーバーライドのサポートが必要ない場合は、AnnotationUtils代わりに使用することを検討してください。

例:

final Named namedAnnotation = AnnotatedElementUtils.findMergedAnnotation(Person.class, Named.class);
final String name = namedAnnotation.name();
assertEquals("Steve", name);
于 2016-04-10T09:08:52.297 に答える
10

複合アノテーションのプロパティをメタ アノテーションの 1 つに渡す方法はありますか?

簡単な答えは「いいえ」だと思います。Personたとえば、どのような注釈が付けられているかを尋ねて取得@Namedする方法はありません。

より複雑な答えは、注釈を連鎖させることはできますが、リフレクションを介してこれらの注釈を調査する必要があるということです。たとえば、次のように動作します。

@Bar
public class Foo {
    public static void main(String[] args) {
        Annotation[] fooAnnotations = Foo.class.getAnnotations();
        assertEquals(1, fooAnnotations.length);
        for (Annotation annotation : fooAnnotations) {
            Annotation[] annotations =
                annotation.annotationType().getAnnotations();
            assertEquals(2, annotations.length);
            assertEquals(Baz.class, annotations[0].annotationType());
        }
    }

    @Baz
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Bar {
    }

    @Retention(RetentionPolicy.RUNTIME)
    public @interface Baz {
    }
}

ただし、次のステートメントは null を返します。

// this always returns null
Baz baz = Foo.class.getAnnotation(Baz.class)

@Bazこれは、注釈を探しているサードパーティ クラスがそれを認識しないことを意味します。

于 2012-04-10T12:40:52.280 に答える