Frage

Ich frage mich, ob es irgendeine Art, wie ich die Anmerkung Informationen einer Klasse zur Laufzeit bekommen? Da möchte ich die Eigenschaften bekommen, dass sepcifily kommentierten.

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 der Hibernate-Suche, und jetzt, was ich will, ist erhalten, die Eigenschaft des „TestMain“ ist kommentiert als ‚Feld‘ (im Beispiel sind sie [Name, Alter] ), und das ist 'gespeichert (store = store.yes)' (im Beispiel sind sie [ Alter ]) zur Laufzeit.

Irgendwelche Ideen?

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=, boost=@org.hibernate.search.annotations.Boost(value=1.0), analyzer=@org.hibernate.search.annotations.Analyzer(impl=void, definition=), bridge=@org.hibernate.search.annotations.FieldBridge(impl=void, params=[]))

                //how to get the parameter value of this an? using the string method?split?
            }
        }

    }
    return fieldList;
}

}

War es hilfreich?

Lösung

Yes, of course. Your code sample does not actually get annotation information for class, but for fields, but code is similar. You just need to get Class, Method or Field you are interested in, then call "getAnnotation(AnnotationClass.class)" on it.

The only other thing to notice is that annotation definition must use proper RetentionPolicy so that annotation information is stored in byte code. Something like:

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

Andere Tipps

It seems you are using (Hibernate Search)! Hibernate Search has a helper class which can retrieve fields informations

FieldInfos fieldInfos = ReaderUtil.getMergedFieldInfos(indexReader);

Unfortunately FieldsInfos does not contain enough informations (typically you don't know if a field is stored or not: or perhaps I missed something). Here is my implementation to get all stored fields:

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

Then it's quite easy to retrieve stored fields of an entity:

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

It should work for:

  • stored attributs (Stored.YES or Stored.COMPRESS)
  • simple attributs (with or without a specified name)
  • embedded attributs (with or without a prefix)
  • multi-fields declaration (ie @Fields annotations)

Hope it can help someone.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top