Подтвердить что ты не робот

Передача свойств аннотации мета-аннотации

Скажем, у меня есть аннотация с свойством:

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

и я хочу создать составную аннотацию с несколькими мета-аннотациями, включая те, которые принимают свойство

@Named
@AnotherAnnotation
@YetAnotherAnnotation
public @interface CompoundAnnotation {

    ...
}

Есть ли способ передать свойства объединенной аннотации одной из мета-аннотаций?

Например, что-то вроде этого:

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

что эквивалентно, но гораздо удобнее, чем

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

Спасибо!

PS извинения за мой плохой выбор аннотации примера - у меня не было javax.inject. @Указанная аннотация в уме, просто какая-то произвольная аннотация, которая имеет свойства.


Спасибо всем за ваши ответы/комментарии.

Кажется, это так, что это невозможно. Тем не менее, просто случается, что для моего случая-в-точке есть простой подход, который я буду использовать в случае, если это кому-то поможет:

Я работаю с Spring и хочу создать свои собственные аннотации, которые @Component как мета-аннотации, таким образом автоопределяются при сканировании компонентов. Однако я также хотел установить свойство BeanName (соответствующее свойству value в @Component), чтобы иметь пользовательские имена bean.

Ну, оказывается, что продуманные ребята из Spring сделали это возможным - AnnotationBeanNameGenerator возьмет свойство "значение" любой аннотации, которую он передал, и использует это как имя bean (и Конечно, по умолчанию он будет получать только аннотации, которые являются @Component или имеют @Component в качестве мета-аннотации). Оглядываясь назад, это должно было быть очевидным для меня с самого начала - так существующие аннотации с @Component как мета-аннотации, такие как @Service и @Registry, могут содержать имена bean.

Надеюсь, что это полезно кому-то. Я по-прежнему считаю стыдно, что это невозможно в целом, хотя!

4b9b3361

Ответ 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, не увидит его.

Ответ 2

Через несколько лет, и поскольку вы используете 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), и удивительно то, что он действительно работает так, как вы ожидали.