2010-12-14 22 views
6

Me pregunto si hay alguna manera de que pueda obtener la información de anotación de una clase en tiempo de ejecución? Como quiero obtener las propiedades anotadas secuencialmente.obtener la información de la anotación en el tiempo de ejecución

Ejemplo:

class TestMain { 
    @Field(
      store = Store.NO) 
    private String name; 
    private String password; 
    @Field(
      store = Store.YES) 
    private int  age; 

    //..........getter and setter 
} 

Las anotaciones provienen de la hibernación-búsqueda, y ahora lo que quiero es conseguir que la propiedad de la "TestMain" se anotado como un 'campo' (en el ejemplo, son [nombre, edad]), y que es 'almacenado (store = store.yes)' (en el ejemplo, son [edad]) en tiempo de ejecución.

¿Alguna idea?

Actualización:

public class FieldUtil { 
public static List<String> getAllFieldsByClass(Class<?> clazz) { 
    Field[] fields = clazz.getDeclaredFields(); 
    ArrayList<String> fieldList = new ArrayList<String>(); 
    ArrayList<String> storedList=new ArrayList<String>(); 
    String tmp; 
    for (int i = 0; i < fields.length; i++) { 
     Field fi = fields[i]; 
     tmp = fi.getName(); 
     if (tmp.equalsIgnoreCase("serialVersionUID")) 
      continue; 
     if (fi.isAnnotationPresent(org.hibernate.search.annotations.Field.class)) { 
      //it is a "field",add it to list. 
      fieldList.add(tmp); 

      //make sure if it is stored also 
      Annotation[] ans = fi.getAnnotations(); 
      for (Annotation an : ans) { 
       //here,how to get the detail annotation information 
       //I print the value of an,it is something like this: 
       //@org.hibernate.search.annotations.Field(termVector=NO, index=UN_TOKENIZED, store=NO, name=, [email protected](value=1.0), [email protected](impl=void, definition=), [email protected](impl=void, params=[])) 

       //how to get the parameter value of this an? using the string method?split? 
      } 
     } 

    } 
    return fieldList; 
} 

}

+0

Es probable que obtenga una respuesta más rápida si agrega una etiqueta con el lenguaje de programación que está utilizando. –

+0

Gracias, lo agrego – hguser

Respuesta

2

Sí, por supuesto. El ejemplo de código no obtiene información de anotación para la clase, pero sí para los campos, pero el código es similar. Solo necesita obtener la Clase, el Método o el Campo que le interesan y luego llamar a "getAnnotation (AnnotationClass.class)".

La única otra cosa que se nota es que la definición de la anotación debe usar RetentionPolicy adecuada para que la información de la anotación se almacene en el código byte. Algo como:

@Target({ElementType.ANNOTATION_TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation { ... } 
+0

Mi código es una clase anotada, y quiero obtener su información de anotación en otro cliente. – hguser

+0

Mientras el tipo de retención sea RUNTIME, las definiciones de anotación se almacenan junto con bytecode de Java, y son accesibles desde cualquier lugar donde se cargue la clase. La única otra cosa que se debe incluir es la clase de anotación en sí (tal vez esto es lo que estabas buscando); en su caso, sería 'Field.class' (para la anotación @Field). – StaxMan

+0

Hola, gracias, ¿puedes dedicar algo de tiempo a revisar mi actualización? :) – hguser

1

¡Parece que está utilizando (Hibernate Search)! Hibernate Search tiene una clase de ayuda que puede recuperar campos informaciones

FieldInfos fieldInfos = ReaderUtil.getMergedFieldInfos(indexReader); 

Desafortunadamente FieldsInfos no contiene suficientes informaciones (por lo general no se conocen a si un campo se almacena o no: o tal vez me haya perdido algo). Aquí está mi aplicación para obtener todos los campos almacenados:

public class HBSearchHelper { 

/** 
* Get all fields of a entity which are stored into Lucene 
* 
* @param clazz 
* @param prefix 
* @return 
*/ 
public static List<String> getStoredField(Class<?> clazz, String prefix) { 
    List<Field> fields = getAllFields(clazz); 
    ArrayList<String> storedList = new ArrayList<String>(); 
    for (Field fi : fields) { 
     // @Field annotation 
     if (fi.isAnnotationPresent(org.hibernate.search.annotations.Field.class)) { 
      org.hibernate.search.annotations.Field annotation = fi.getAnnotation(org.hibernate.search.annotations.Field.class); 
      String storedName = getStoredFieldName(fi.getName(), annotation); 
      if (storedName != null) { 
       storedList.add(prefix + storedName); 
      } 
     } 
     // @Fields annotation (should contain one or more @Field annotations) 
     if (fi.isAnnotationPresent(org.hibernate.search.annotations.Fields.class)) { 
      org.hibernate.search.annotations.Fields annotation = fi.getAnnotation(org.hibernate.search.annotations.Fields.class); 
      org.hibernate.search.annotations.Field[] subAnnotations = annotation.value(); 
      for (org.hibernate.search.annotations.Field subAnnotation : subAnnotations) { 
       String storedName = getStoredFieldName(fi.getName(), subAnnotation); 
       if (storedName != null) { 
        storedList.add(prefix + storedName); 
       } 
      } 
     } 
     // @IndexedEmbeded annotation 
     if (fi.isAnnotationPresent(org.hibernate.search.annotations.IndexedEmbedded.class)) { 
      org.hibernate.search.annotations.IndexedEmbedded annotation = fi.getAnnotation(org.hibernate.search.annotations.IndexedEmbedded.class); 
      String name = fi.getName(); 
      // If the annotation has declared a prefix then use it instead of the field's name 
      if (annotation.prefix() != null && !annotation.prefix().isEmpty() && !annotation.prefix().equals(".")) { 
       name = annotation.prefix(); 
      } 
      Class<?> embeddedClass = fi.getType(); 
      if (Collection.class.isAssignableFrom(embeddedClass)) { 
       Type embeddedType = fi.getGenericType(); 
       if (embeddedType instanceof ParameterizedType) { 
        Type[] argsType = ((ParameterizedType) embeddedType).getActualTypeArguments(); 
        if (argsType != null && argsType.length > 0) { 
         embeddedClass = (Class<?>) argsType[0]; 
        } 
       } 
      } 
      List<String> nestedFields = getStoredField(embeddedClass, prefix + name + "."); 
      if (nestedFields != null && !nestedFields.isEmpty()) { 
       storedList.addAll(nestedFields); 
      } 
     } 
    } 
    return storedList; 
} 

/** 
* Returns the @Field's name if this @Field is stored otherwise returns null 
* 
* @param propertyName 
*   The name of the bean's property 
* @param field 
*   The declared Hibernate Search annotation 
* @return 
*/ 
private static String getStoredFieldName(String propertyName, org.hibernate.search.annotations.Field annotation) { 
    Store store = annotation.store(); 
    if (store == Store.YES || store == Store.COMPRESS) { 
     String name = propertyName; 
     // If the annotation has declared a name then use it instead of the property's name 
     if (annotation.name() != null && !annotation.name().isEmpty()) { 
      name = annotation.name(); 
     } 
     return name; 
    } 
    return null; 
} 

/** 
* Get all declared fields from the class and its super types 
* 
* @param type 
* @return 
*/ 
private static List<Field> getAllFields(Class<?> type) { 
    List<Field> fields = new ArrayList<Field>(); 
    if (type != null) { 
     fields.addAll(Arrays.asList(type.getDeclaredFields())); 
     fields.addAll(getAllFields(type.getSuperclass())); 
    } 
    return fields; 
} 
} 

Entonces es muy fácil de recuperar los campos almacenados de una entidad:

List<String> storedFields = HBSearchHelper.getStoredFields(MyEntity.class, ""); 

Se debe trabajar para:

  • attributs almacenados (Stored.YES o Stored.COMPRESS)
  • atribuciones simples (con o sin un nombre especificado)
  • attributs incrustadas (con o sin un prefijo)
  • declaración de varios campos (es decir @Fields anotaciones)

esperan que los pueda ayudar a alguien.

Cuestiones relacionadas