2012-04-10 2 views
18

Скажем, у меня есть аннотацию со свойством:Передача аннотаций свойств мета-аннотаций

@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 и хочу создать свои собственные аннотации, Компонент в виде мета-аннотации, автоматически определяемый при сканировании компонентов. Тем не менее, я также хотел установить свойство BeanName (соответствующее свойству value в @Component), чтобы у меня были пользовательские имена компонентов.

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

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

+0

Я не вижу, как, если вы не добавляете аннотации через обработку байтового кода во время загрузки. (Или, может быть, пользовательский обработчик аннотаций.) Любопытно посмотреть, что все возможно без трюков. –

+0

Просто размышляя здесь, не будет ли это обходным путем, если бы у вас был базовый класс, аннотированный с помощью AnotherAnnotation и YAA, а затем расширенный класс Person? Посмотрите также на Размышления, возможно, вы получите некоторые идеи: http://code.google.com/p/reflections/ – maksimov

+0

Связано с http://stackoverflow.com/questions/1624084/why-is-not-possible- к простираться-аннотаций-в-Java – Gray

ответ

6

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

Я думаю, что простой ответ «нет». Невозможно спросить 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 { 
    } 
} 

Однако следующее утверждение возвратит нуль:

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

Это означает, что любая третья сторона, класс ищет @Baz аннотацию не увидит.

14

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

Смежные вопросы