2012-04-10 24 views
18

Decir que tengo una anotación con una propiedad:Pasando propiedades de anotación a meta-anotaciones

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

y quiero crear una anotación compuesto con varios-anotaciones meta, entre ellos el que lleva una propiedad

@Named 
@AnotherAnnotation 
@YetAnotherAnnotation 
public @interface CompoundAnnotation { 

    ... 
} 

¿Hay alguna manera de que pueda pasar propiedades a la anotación compuesta a una de las metaanotaciones?

Por ejemplo, algo como esto:

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

que es equivalente a, pero mucho más conveniente que

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

Gracias!

PD: disculpas por mi mala elección de una anotación de ejemplo. No tenía la anotación javax.inject. @ Named en mente, solo una anotación arbitraria que tiene propiedades.


Gracias a todos por sus respuestas/comentarios.

Definitivamente parece ser el caso de que esto no es posible. Sin embargo, simplemente sucede que hay un simple repaso para mi caso-en-punto, que compartiré en caso de que ayude a alguien:

Estoy trabajando con Spring y quiero crear mis propias anotaciones que tengan @ Componente como una meta-anotación, por lo que se detecta automáticamente mediante el escaneo de componentes. Sin embargo, también quería poder establecer la propiedad BeanName (que corresponde a la propiedad value en @Component) para poder tener nombres de bean personalizados.

Bueno, resulta que los muchachos pensativos en Spring hicieron posible hacer eso, el AnnotationBeanNameGenerator tomará la propiedad 'value' de cualquier anotación que se pase y la usará como el nombre del bean (y, por supuesto, por por defecto, solo recibirán anotaciones pasadas que son @Component o tienen @Component como meta-anotación). En retrospectiva, esto debería haber sido obvio para mí desde el principio: así es como las anotaciones existentes con @Component como una metaanotación, como @Service y @Registry, pueden proporcionar nombres de beans.

Espero que sea útil para alguien. ¡Todavía creo que es una pena que esto no sea posible de manera más general!

+0

No veo cómo, a menos que esté agregando anotaciones a través de la manipulación de código byte en tiempo de carga. (O un procesador de anotación personalizado, supongo.) Sin embargo, es curioso ver todo lo que es posible sin trucos. –

+0

Solo pensando en voz alta aquí, ¿no será una solución si tuviera una clase base anotada con AnotherAnnotation y YAA, y entonces la clase Person extendió eso? Mire Reflections también, tal vez obtenga algunas ideas: http://code.google.com/p/reflections/ – maksimov

+0

relacionado con http://stackoverflow.com/questions/1624084/why-is-not-possible- to-extend-annotations-in-java – Gray

Respuesta

6

¿Hay alguna forma de que pueda pasar propiedades a la anotación compuesta a una de las metaanotaciones?

Creo que la respuesta simple es "no". No hay forma de preguntar Person qué anotaciones tiene y obtener @Named por ejemplo.

La respuesta más compleja es que puede encadenar anotaciones, pero tendría que investigar estas anotaciones a través de la reflexión.Por ejemplo, las siguientes obras:

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

Sin embargo, la siguiente declaración volverán nulo:

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

Esto significa que cualquier clase tercera parte que está buscando la anotación @Baz no lo verá.

14

Hace algunos años, y como está utilizando Spring, lo que está buscando ahora es posible utilizando la anotación @AliasFor.

Por ejemplo:

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

Ahora puede anotar su prueba con @SpringContextTest(MyConfig.class), y lo más sorprendente es que en realidad funciona de la manera que cabría esperar.