2012-04-10 11 views
18

Say mam adnotację z właściwością:Przekazanie własności adnotację do meta-adnotacji

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

i chcę utworzyć adnotację związek z kilkoma meta adnotacji, w tym jedno, które ma właściwość

@Named 
@AnotherAnnotation 
@YetAnotherAnnotation 
public @interface CompoundAnnotation { 

    ... 
} 

Czy istnieje sposób przekazania właściwości do złożonej adnotacji do jednej z adnotacji meta?

Np coś takiego:

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

które jest równoważne, ale znacznie wygodniejsze niż

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

dzięki!

PS przeprosiny za mój zły wybór przykładowej adnotacji - Nie miałem javax.inject. @ Wspomniana adnotacja ma na uwadze, tylko niektóre arbitralne adnotacje, które mają właściwości.


Dziękuję wszystkim za odpowiedzi/komentarze.

Zdecydowanie wydaje się, że nie jest to możliwe. Zdarza się jednak, że jest to prosta praca dla mojej sprawy, którą podzielę się na wypadek, gdyby pomogło komukolwiek:

Pracuję ze Spring i chcę tworzyć własne adnotacje, które mają @ Komponent jako meta-adnotacja, dzięki czemu jest automatycznie wykrywany przez skanowanie komponentów. Jednak chciałem również móc ustawić właściwość BeanName (odpowiadającą właściwości value w @ Component), więc mogłem mieć niestandardowe nazwy komponentów.

Cóż, okazuje się, że myślący ludzie na Springu mogli to zrobić - AnnotationBeanNameGenerator weźmie wartość "value" dowolnej adnotacji, która została przekazana i użyje jej jako nazwy fasoli (i oczywiście przez domyślnie otrzyma tylko przekazane adnotacje, które są @Component lub mają @Component jako meta-adnotacje). Z perspektywy czasu powinno to być dla mnie oczywiste od samego początku - tak właśnie istniejące adnotacje z @ Component jako meta-adnotacji, takie jak @Service i @Registry, mogą dostarczać nazwy fasoli.

Nadzieja, która jest przydatna dla kogoś. Nadal uważam, że szkoda, że ​​nie jest to możliwe bardziej ogólnie!

+0

Nie widzę, jak to zrobić, chyba że dodajesz adnotacje poprzez manipulację kodami bajtowymi w czasie ładowania. (Przypuszczam, że jest to też procesor adnotacji niestandardowej). Ciekawe, aby zobaczyć, co jest możliwe bez trików. –

+0

Po prostu myśląc głośno, czy to nie będzie obejście problemu, jeśli masz klasę bazową z adnotacją InnaNauka i YAA, a następnie klasa Person je rozszerzyła? Spójrz też na Reflections, może dostaniesz kilka pomysłów: http://code.google.com/p/reflections/ – maksimov

+0

Podobne do http://stackoverflow.com/questions/1624084/why-is-not-possible- do-rozszerzenia-adnotacji-w-java – Gray

Odpowiedz

6

Czy istnieje sposób, w jaki można przekazać właściwości do złożonej adnotacji do jednej z adnotacji meta?

Myślę, że prosta odpowiedź brzmi "nie". Nie ma sposobu, aby zapytać o to, jakie adnotacje ma na ten temat, na przykład: @Named.

Bardziej złożoną odpowiedzią jest to, że można łączyć adnotacje, ale trzeba zbadać te adnotacje za pomocą refleksji.Na przykład, następujące prace:

@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 { 
    } 
} 

jednak następujące oświadczenie zwróci NULL:

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

Oznacza to, że każdy 3-te klasa partia, która szuka dla @Baz adnotacji nie będzie go zobaczyć.

14

Jest kilka lat później, a ponieważ używasz Springa, to o co prosisz, jest teraz możliwe za pomocą adnotacji @AliasFor.

Na przykład:

@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 {}; 
} 

Teraz można opisywać test z @SpringContextTest(MyConfig.class) i zadziwiające jest to, że faktycznie działa tak, jak można by oczekiwać.