2010-12-14 34 views
6

Zastanawiam się, czy istnieje sposób można uzyskać informacje o adnotacji klasy w czasie wykonywania? Ponieważ chcę uzyskać właściwości, które w sposób przenikliwy zostały opisane.uzyskać informacje o adnotacji w czasie wykonywania

Przykład:

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

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

Adnotacje pochodzą z hibernacji-search, a teraz to, co chcę, to dostać których własność „TestMain” jest adnotacjami jako „pola” (w przykładzie, są to: [imię i nazwisko, wiek]) i "przechowywany (store = store.yes)" (w przykładzie są one [wiek]) w czasie wykonywania.

Wszelkie pomysły?

UPDATE:

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

Prawdopodobnie szybciej uzyskasz odpowiedź, jeśli dodasz tag z językiem programowania, którego używasz. –

+0

Dzięki, dodaję go – hguser

Odpowiedz

2

Tak, oczywiście. Twój przykładowy kod faktycznie nie pobiera informacji o adnotacjach dla klasy, ale dla pól, ale kod jest podobny. Trzeba tylko uzyskać klasę, metodę lub pole, którymi jesteś zainteresowany, a następnie wywołać na nim "getAnnotation (AnnotationClass.class)".

Należy zwrócić uwagę na to, że definicja adnotacji musi używać odpowiedniej RetentionPolicy, aby informacje o adnotacjach były przechowywane w kodzie bajtowym. Coś jak:

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

Mój kod jest przypisany do klasy i chcę uzyskać jego informacje o adnotacjach w innym kliencie. – hguser

+0

Tak długo jak typem przechowywania jest RUNTIME, definicje adnotacji są przechowywane razem z kodem bajtowym Java i są dostępne wszędzie tam, gdzie jest załadowana klasa. Jedyną inną rzeczą, którą należy uwzględnić, jest sama klasa adnotacji (może tego właśnie szukałeś?); w twoim przypadku byłaby to "Field.class" (dla adnotacji @Field). – StaxMan

+0

Witam, dziękuję, czy możesz poświęcić trochę czasu na sprawdzenie mojej aktualizacji? :) – hguser

1

Wygląda na to, że używasz (wyszukiwanie w trybie hibernacji)! Hibernate Search ma klasy pomocnika, który można pobrać pola informacji

FieldInfos fieldInfos = ReaderUtil.getMergedFieldInfos(indexReader); 

Niestety FieldsInfos nie zawiera wystarczających informacji (zwykle nie wiem, czy pole jest przechowywany lub nie: czy może coś mi umknęło). Oto moja realizacja, aby wszystkie zapisane pola:

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

Wtedy to dość łatwo odzyskać zapisane pola jednostki:

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

powinno działać dla:

  • przechowywanych attributs (Stored.YES lub Stored.COMPRESS)
  • proste przydziały (z lub bez określonej nazwy)
  • osadzone attributs (z lub bez prefiksu)
  • deklaracji wielu dziedzinach (tj @Fields adnotacji)

Nadzieję, że może komuś pomóc.

Powiązane problemy