2010-12-14 1 views
6

Интересно, есть ли способ получить информацию о аннотации класса во время выполнения? Поскольку я хочу получить свойства, которые могут быть аннотированы.получить информацию о аннотации во время выполнения

Пример:

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

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

Аннотация приходит из спящего режима-поиска, и теперь то, что я хочу получить, который свойство «TestMain» является аннотированным как «поле» (в примере, это [имя, возраст]) и который «хранится (store = store.yes)» (в примере они [возраст]) во время выполнения.

Любые идеи?

ОБНОВЛЕНИЕ:

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

Скорее всего, вы получите ответ быстрее, если вы добавите тег с языком программирования, который вы используете. –

+0

Спасибо, я добавляю – hguser

ответ

2

Да, конечно. В вашем примере кода на самом деле не получаются данные аннотации для класса, а для полей, но код аналогичен. Вам просто нужно получить класс, метод или поле, которое вас интересует, а затем называть «getAnnotation (AnnotationClass.class)».

Единственное, что следует заметить, это то, что определение аннотации должно использовать надлежащую RetentionPolicy, чтобы информация аннотации хранилась в байтовом коде. Что-то вроде:

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

Мой код является аннотированным классом, и я хочу получить его информацию о комментариях в другом клиенте. – hguser

+0

Пока тип хранения является RUNTIME, определения аннотаций сохраняются вместе с байт-кодом Java и доступны в любом месте, где загружен класс. Единственное, что нужно включить, это класс аннотаций (может быть, это то, что вы искали?); в вашем случае это будет «Field.class» (для аннотации @Field). – StaxMan

+0

Привет, спасибо, можете ли вы сэкономить время на проверку моего обновления? :) – hguser

1

Кажется, вы используете (Hibernate Search)! Hibernate Search имеет вспомогательный класс, который может извлекать информацию полого

FieldInfos fieldInfos = ReaderUtil.getMergedFieldInfos(indexReader); 

К сожалению FieldsInfos не содержит достаточно информации (как правило, вы не знаете, если поле хранятся или нет: или, возможно, я что-то пропустил). Вот моя реализация, чтобы получить все сохраненные поля:

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

Тогда это довольно легко получить сохраненные поля объекта:

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

Она должна работать на:

  • хранящимся attributs (Stored.YES или Stored.COMPRESS)
  • простые атрибуты (с указанным именем или без указанного)
  • встроенные attributs (с или без префикса)
  • нескольких полой декларации (т.е. @fields аннотаций)

Надеются, что это может помочь кому-то.