2010-12-14 20 views
6

Ich frage mich, ob es eine Möglichkeit gibt, die Annotationsinformationen einer Klasse zur Laufzeit zu bekommen? Da ich die Eigenschaften erhalten möchte, die annotiert sind.die Annotationsinformationen zur Laufzeit abrufen

Beispiel:

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

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

Die Anmerkungen stammen aus dem Hibernate-Suche, und jetzt, was ich will, ist erhalten die Eigenschaft des „TestMain“ wird als ‚Feld‘ Anmerkungen versehen (im Beispiel: Sie sind [Name, Alter]), und das ist 'gespeichert (Speicher = store.yes)' (im Beispiel sind sie [Alter]) zur Laufzeit.

Irgendwelche Ideen?

AKTUALISIERUNG:

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), a[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

Sie erhalten wahrscheinlich schneller eine Antwort, wenn Sie ein Tag mit der von Ihnen verwendeten Programmiersprache hinzufügen. –

+0

Danke, ich füge es hinzu – hguser

Antwort

2

Ja, natürlich. Ihr Codebeispiel erhält keine Annotationsinformationen für die Klasse, sondern für Felder, der Code ist jedoch ähnlich. Sie müssen nur Klasse, Methode oder Feld, an dem Sie interessiert sind, aufrufen und dann "getAnnotation (AnnotationClass.class)" darauf aufrufen.

Die einzige andere Sache zu beachten ist, dass Annotation-Definition richtige RetentionPolicy verwenden muss, so dass Annotationsinformationen in Byte-Code gespeichert werden. Etwas wie:

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

Mein Code ist eine Klasse mit Anmerkungen, und ich möchte seine Annotationsinformationen in anderen Client erhalten. – hguser

+0

Solange der Aufbewahrungstyp RUNTIME ist, werden Annotationsdefinitionen zusammen mit Java-Bytecode gespeichert und sind überall verfügbar, wo die Klasse geladen wird. Die einzige andere Sache ist die Annotationsklasse selbst (vielleicht ist das was du gesucht hast?); in Ihrem Fall wäre es "Field.class" (für @ Field Annotation). – StaxMan

+0

Hallo, danke, kannst du etwas Zeit für einen Check bei meinem Update haben? :) – hguser

1

Es scheint, Sie verwenden (Hibernate Search)! Hibernate Search eine Hilfsklasse hat, die Informationen abrufen können Felder

FieldInfos fieldInfos = ReaderUtil.getMergedFieldInfos(indexReader); 

Leider FieldsInfos nicht genügend Informationen enthalten (in der Regel wissen Sie nicht, ob ein Feld gespeichert ist oder nicht: oder vielleicht habe ich etwas verpasst). Hier ist meine Implementierung alle gespeicherten Felder zu erhalten:

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

Dann ist es ganz einfach gespeichert Felder eines Unternehmens abzurufen:

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

Es sollte für Arbeit:

  • gespeichert attributs (Stored.YES oder Stored.COMPRESS)
  • einfache Attribute (mit oder ohne einen angegebenen Namen)
  • eingebettet attributs (mit oder ohne Präfix)
  • Multi-Felder Erklärung (dh @Fields Anmerkungen)

Hoffe es kann jemand helfen.