получить информацию об аннотации во время выполнения

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

Пример:

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

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

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

Любые идеи?

Обновить:

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

}


person hguser    schedule 14.12.2010    source источник
comment
Скорее всего, вы получите ответ быстрее, если добавите тег с языком программирования, который используете.   -  person Matthew Frederick    schedule 14.12.2010


Ответы (2)


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

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

@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation { ... }
person StaxMan    schedule 14.12.2010
comment
Мой код представляет собой аннотированный класс, и я хочу получить его аннотацию в другом клиенте. - person hguser; 14.12.2010
comment
Пока тип хранения RUNTIME, определения аннотаций сохраняются вместе с байт-кодом Java и доступны в любом месте, где загружается класс. Единственное, что еще нужно включить, это сам класс аннотаций (может быть, это то, что вы искали?); в вашем случае это будет «Field.class» (для аннотации @Field). - person StaxMan; 14.12.2010
comment
Привет, спасибо, не могли бы вы уделить немного времени, чтобы проверить мое обновление? :) - person hguser; 15.12.2010
comment
Конечно. Все, что вам нужно сделать, это выполнить 'fi.getAnnotation(org.hibernate.search.annotations.Field.class)'; и после этого у экземпляра аннотации есть аксессоры. Это просто довольно обычный объект, поэтому вызывайте для него методы. Чтобы узнать, какие методы доступны, проверьте в Javadocs тип аннотации (поле). - person StaxMan; 16.12.2010

Кажется, вы используете (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, "");

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

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

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

person Eric Taix    schedule 25.04.2013