2010-12-14 59 views
6

Je me demande si je peux obtenir les informations d'annotation d'une classe à l'exécution? Puisque je veux obtenir les propriétés qui ont été annotées.obtenir les informations d'annotation à l'exécution

Exemple:

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

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

Les annotations proviennent de la mise en veille prolongée à la recherche d', et maintenant ce que je veux est d'obtenir que la propriété du « TestMain » est annotés comme un « champ » (dans l'exemple, ils sont [nom, âge]), et qui est 'stocké (store = store.yes)' (dans l'exemple, ils sont [age]) lors de l'exécution.

Des idées?

Mise à jour:

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]Analyzer(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

Vous obtiendrez probablement une réponse plus rapidement si vous ajoutez un tag au langage de programmation que vous utilisez. –

+0

Merci, je l'ajoute – hguser

Répondre

2

Oui, bien sûr. Votre exemple de code n'obtient pas réellement d'informations d'annotation pour la classe, mais pour les champs, mais le code est similaire. Vous avez juste besoin d'obtenir la classe, la méthode ou le champ qui vous intéresse, puis appelez "getAnnotation (AnnotationClass.class)". La seule autre chose à remarquer est que la définition d'annotation doit utiliser la propriété RetentionPolicy appropriée pour que les informations d'annotation soient stockées dans le code octet. Quelque chose comme:

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

Mon code est une classe annotée, et je veux obtenir ses informations d'annotation dans un autre client. – hguser

+0

Tant que le type de rétention est RUNTIME, les définitions d'annotations sont stockées avec le bytecode Java et sont accessibles partout où la classe est chargée. La seule autre chose à inclure est la classe d'annotation elle-même (c'est peut-être ce que vous cherchiez?); dans votre cas, ce serait 'Field.class' (pour l'annotation @Field). – StaxMan

+0

Salut, merci, pouvez-vous prendre le temps de vérifier ma mise à jour? :) – hguser

1

Il semble que vous utilisez (Hibernate Search)! Hibernate Search a une classe d'aide qui peut récupérer des champs informations

FieldInfos fieldInfos = ReaderUtil.getMergedFieldInfos(indexReader); 

Malheureusement FieldsInfos ne contient pas suffisamment d'informations (en général, vous ne savez pas si un champ est stocké ou non: ou peut-être que je manqué quelque chose). Voici ma mise en œuvre pour obtenir tous les champs stockés:

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

Ensuite, il est très facile de récupérer des champs stockés d'une entité:

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

Il devrait fonctionner pour:

  • attributes stockées (Stored.YES ou Stored.COMPRESS)
  • attributs simples (avec ou sans nom spécifié)
  • attributes embarqués (avec ou sans préfixe)
  • déclaration multi-domaines (par exemple @Fields annotations)

espère que cela peut aider quelqu'un.