2010-11-28 18 views
74

este es mi código:¿Es posible leer el valor de una anotación en java?

@Column(columnName="firstname") 


private String firstName; 

@Column(columnName="lastname") 
private String lastName; 

public String getFirstName() { 
    return firstName; 
} 

public void setFirstName(String firstName) { 
    this.firstName = firstName; 
} 

public String getLastName() { 
    return lastName; 
} 

public void setLastName(String lastName) { 
    this.lastName = lastName; 
} 

es posible leer el valor de mi @Column (columnName = "XYZ123") en otra clase?

Respuesta

19

Nunca lo he hecho, pero parece que Reflection proporciona esto. Field es un AnnotatedElement y entonces tiene getAnnotation. This page tiene un ejemplo (copiado a continuación); bastante sencillo si conoce la clase de la anotación y si la política de anotación retiene la anotación en tiempo de ejecución. Naturalmente, si la política de retención no mantiene la anotación en tiempo de ejecución, no podrá consultarla en tiempo de ejecución.

Una respuesta que se ha eliminado desde entonces (?) Proporcionó un enlace útil al an annotations tutorial que puede ser útil; Copié el enlace aquí para que la gente pueda usarlo.

Ejemplo de this page:

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.reflect.Method; 

@Retention(RetentionPolicy.RUNTIME) 
@interface MyAnno { 
    String str(); 

    int val(); 
} 

class Meta { 
    @MyAnno(str = "Two Parameters", val = 19) 
    public static void myMeth(String str, int i) { 
    Meta ob = new Meta(); 

    try { 
     Class c = ob.getClass(); 

     Method m = c.getMethod("myMeth", String.class, int.class); 

     MyAnno anno = m.getAnnotation(MyAnno.class); 

     System.out.println(anno.str() + " " + anno.val()); 
    } catch (NoSuchMethodException exc) { 
     System.out.println("Method Not Found."); 
    } 
    } 

    public static void main(String args[]) { 
    myMeth("test", 10); 
    } 
} 
85

Sí, si su anotación columna tiene la retención de tiempo de ejecución

@Retention(RetentionPolicy.RUNTIME) 
@interface Column { 
    .... 
} 

que puede hacer algo como esto

for (Field f: MyClass.class.getFields()) { 
    Column column = f.getAnnotation(Column.class); 
    if (column != null) 
     System.out.println(column.columnName()); 
} 
+1

me gusta su solución. ¿Cómo podemos hacer que sea más genérico como que en lugar de MyClass quiero usar T like for (Campo f: T.class.getFields()) { Columna column = f.getAnnotation (Column.class); if (column! = Null) System.out.println (column.columnName()); } – ATHER

+0

¡Exactamente! He estado luchando para resolver eso también. ¿Qué pasa si quiero tener un procesador de anotaciones que no necesita ser provisto explícitamente con un nombre de clase? ¿Se puede hacer para recogerlo del contexto; 'esta'?? – 5122014009

+0

No estoy seguro de entender lo que ustedes dos necesitan. Por favor, pregunte eso como una nueva pregunta con un ejemplo completo. Puede vincularlo aquí si lo desea. – Cephalopod

66

Por supuesto que es. Aquí es una anotación de la muestra:

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface TestAnnotation 
{ 
    String testText(); 
} 

y un método anotado muestra:

class TestClass 
{ 
    @TestAnnotation(testText="zyx") 
    public void doSomething(){} 
} 

Y un método de muestreo en otra clase que imprime el valor de la testText:

Method[] methods = TestClass.class.getMethods(); 
for (Method m : methods) 
{ 
     if (m.isAnnotationPresent(TestAnnotation.class)) 
    { 
     TestAnnotation ta = m.getAnnotation(TestAnnotation.class); 
     System.out.println(ta.testText()); 
    } 
} 
No

mucho diferente para las anotaciones de campo como la tuya.

Cheerz!

+1

guau, ¡muy bien! Gracias por el simple ejemplo. Ilustra claramente el proceso paso a paso. –

+1

Explicación muy buena del proceso de recuperación de los valores de las anotaciones. – Arlind

4

Si bien todas las respuestas dadas hasta el momento son perfectamente válidas, también se debe tener en cuenta el google reflections library para un enfoque más genérico y fácil para el escaneo de anotaciones, p.

Reflections reflections = new Reflections("my.project.prefix"); 

Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class); 
2

También puede utilizar los tipos genéricos, en mi caso, teniendo en cuenta todo lo dicho antes de poder hacer algo como:

public class SomeTypeManager<T> { 

    public SomeTypeManager(T someGeneric) { 

     //That's how you can achieve all previously said, with generic types. 
     Annotation[] an = someGeneric.getClass().getAnnotations(); 

    } 

} 

Recuerde que esto no Equival al 100% a SomeClass. class.get (...)();

Pero puede hacer el truco ...

3

La elaboración de la respuesta de @Cephalopod, si desea todos los nombres de columna en una lista que podría utilizar este oneliner:

List<String> columns = 
     Arrays.asList(MyClass.class.getFields()) 
       .stream() 
       .filter(f -> f.getAnnotation(Column.class)!=null) 
       .map(f -> f.getAnnotation(Column.class).columnName()) 
       .collect(Collectors.toList()); 
+0

Objects.nonNull para abarcar completamente Java 8 :) .filter (f -> nonNull (f.getAnnotation (Column.class))) – dehumanizer

1

En caso común que tiene acceso privado para los campos, para que puedas' T usa getFields en la reflexión. En lugar de esto, usted debe utilizar getDeclaredFields

Así, en primer lugar, debe tener en cuenta si su anotación columna tiene la retención de tiempo de ejecución:

@Retention(RetentionPolicy.RUNTIME) 
@interface Column { 
} 

Después de que usted puede hacer algo como esto:

for (Field f: MyClass.class.getDeclaredFields()) { 
    Column column = f.getAnnotation(Column.class); 
     // ... 
} 

Obviamente, le gustaría hacer algo con el campo - establecer un nuevo valor usando el valor de anotación:

Column annotation = f.getAnnotation(Column.class); 
if (annotation != null) { 
    new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
     object, 
     myCoolProcessing(
      annotation.value() 
     ) 
    ); 
} 

Por lo tanto, el código completo se puede veía así:

for (Field f : MyClass.class.getDeclaredFields()) { 
    Column annotation = f.getAnnotation(Column.class); 
    if (annotation != null) 
     new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
       object, 
       myCoolProcessing(
         annotation.value() 
       ) 
     ); 
} 
Cuestiones relacionadas