実行時に注釈情報を取得します
-
09-10-2019 - |
質問
実行時にクラスの注釈情報を取得できる方法があるのだろうか? Sepcifilyが注釈を付けたプロパティを取得したいので。
例:
class TestMain {
@Field(
store = Store.NO)
private String name;
private String password;
@Field(
store = Store.YES)
private int age;
//..........getter and setter
}
注釈はHibernate-Searchからのものであり、今私が望んでいるのは、「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=, 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;
}
}
解決
はい、もちろん。コードサンプルは実際にはクラスの注釈情報を取得するのではなく、フィールドでは入手しますが、コードは似ています。興味のあるクラス、方法、またはフィールドを取得するだけで、「getannotation(annotationclass.class)」と呼びます。
注目すべき唯一のことは、注釈の定義が適切な保持ポリティを使用して、アノテーション情報がバイトコードに保存されるようにしなければならないということです。何かのようなもの:
@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation { ... }
他のヒント
(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, "");
それは次のように機能するはずです:
- 保存された属性(YEESまたはSTORED.COMPRESS)
- 単純な属性(指定された名前の有無にかかわらず)
- 埋め込まれた属性(プレフィックスの有無にかかわらず)
- マルチフィールド宣言(すなわち@fieldsアノテーション)
それが誰かを助けることができることを願っています。
所属していません StackOverflow