2010-12-15 47 views
46

我想知道一個類的某些成員變量的註釋,我使用BeanInfo beanInfo = Introspector.getBeanInfo(User.class)來反思一個類,並使用BeanInfo.getPropertyDescriptors()來查找特定的屬性,並使用類type = propertyDescriptor.getPropertyType()來獲取屬性的類。如何獲取成員變量的註釋?

但我不知道如何獲得註釋添加到成員變量?

我試過type.getAnnotations()type.getDeclaredAnnotations(),但都返回類的註釋,不是我想要的。例如:

class User 
{ 
    @Id 
    private Long id; 

    @Column(name="ADDRESS_ID") 
    private Address address; 

    // getters , setters 
} 

@Entity 
@Table(name = "Address") 
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
class Address 
{ 
    ... 
} 

我想要得到的地址的註釋:@Column,不類地址的註解(@實體,@Table,@Cache)。如何實現它?謝謝。

+1

@Bozho如果複製數據庫對象,似乎這裏是這種情況可能是有用的。如果副本應該成爲不同的DB實體,副本不能具有相同的ID。通用複製算法可以用Annotation'@Id'排除任何內容。 – Hok 2014-02-26 09:04:28

回答

8

你必須使用反射來獲取User類的所有成員字段,遍歷它們,找到自己的註解

是這樣的:

public void getAnnotations(Class clazz){ 
    for(Field field : clazz.getDeclaredFields()){ 
     Class type = field.getType(); 
     String name = field.getName(); 
     field.getDeclaredAnnotations(); //do something to these 
    } 
} 
+1

謝謝,但我的clazz沒有公開的無參數構造函數...(對不起沒有提及)。所以,clazz.newInstance()將不起作用。 – smallufo 2010-12-15 18:21:55

+1

只是省略了clazz.newInstance()這一行,我不確定mkoryak爲什麼包含它 - 它沒有被任何東西使用。 – qualidafial 2010-12-15 19:16:27

+1

oops,我沒有正確粘貼代碼。它實際上用於 – mkoryak 2010-12-15 19:23:53

5

你可以在getter方法的註釋:

propertyDescriptor.getReadMethod().getDeclaredAnnotations(); 

獲取私有字段的註釋似乎是一個糟糕的主意......如果該屬性甚至不是一個領域的支持,或者是由不同名稱的字段支持?即使忽略這些情況,你也會通過查看私人內容來打破抽象。

+0

謝謝,但是如果我不能修改這個類的代碼呢?如果我必須得到私人領域的註釋怎麼辦? – smallufo 2010-12-15 18:24:13

+0

@smallufo我真的很好奇,知道爲什麼你需要這個。如果註釋是在私人領域,那麼你不打算知道他們。 – 2010-12-15 21:22:14

+3

嗨,因爲我們的代碼遵循很多JPA的教程。大多數JPA教程/書籍直接在私有字段中添加註釋。我想挖掘的是這些JPA註釋。 – smallufo 2010-12-16 02:13:15

2
package be.fery.annotation; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.PrePersist; 

@Entity 
public class User { 
    @Id 
    private Long id; 

    @Column(name = "ADDRESS_ID") 
    private Address address; 

    @PrePersist 
    public void doStuff(){ 

    } 
} 

而且測試類:

package be.fery.annotation; 

import java.lang.annotation.Annotation; 
import java.lang.reflect.Field; 
import java.lang.reflect.Method; 

public class AnnotationIntrospector { 

    public AnnotationIntrospector() { 
     super(); 
    } 

    public Annotation[] findClassAnnotation(Class<?> clazz) { 
     return clazz.getAnnotations(); 
    } 

    public Annotation[] findMethodAnnotation(Class<?> clazz, String methodName) { 

     Annotation[] annotations = null; 
     try { 
      Class<?>[] params = null; 
      Method method = clazz.getDeclaredMethod(methodName, params); 
      if (method != null) { 
       annotations = method.getAnnotations(); 
      } 
     } catch (SecurityException e) { 
      e.printStackTrace(); 
     } catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
     } 
     return annotations; 
    } 

    public Annotation[] findFieldAnnotation(Class<?> clazz, String fieldName) { 
     Annotation[] annotations = null; 
     try { 
      Field field = clazz.getDeclaredField(fieldName); 
      if (field != null) { 
       annotations = field.getAnnotations(); 
      } 
     } catch (SecurityException e) { 
      e.printStackTrace(); 
     } catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } 
     return annotations; 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     AnnotationIntrospector ai = new AnnotationIntrospector(); 
     Annotation[] annotations; 
     Class<User> userClass = User.class; 
     String methodDoStuff = "doStuff"; 
     String fieldId = "id"; 
     String fieldAddress = "address"; 

     // Find class annotations 
     annotations = ai.findClassAnnotation(be.fery.annotation.User.class); 
     System.out.println("Annotation on class '" + userClass.getName() 
       + "' are:"); 
     showAnnotations(annotations); 

     // Find method annotations 
     annotations = ai.findMethodAnnotation(User.class, methodDoStuff); 
     System.out.println("Annotation on method '" + methodDoStuff + "' are:"); 
     showAnnotations(annotations); 

     // Find field annotations 
     annotations = ai.findFieldAnnotation(User.class, fieldId); 
     System.out.println("Annotation on field '" + fieldId + "' are:"); 
     showAnnotations(annotations); 

     annotations = ai.findFieldAnnotation(User.class, fieldAddress); 
     System.out.println("Annotation on field '" + fieldAddress + "' are:"); 
     showAnnotations(annotations); 

    } 

    public static void showAnnotations(Annotation[] ann) { 
     if (ann == null) 
      return; 
     for (Annotation a : ann) { 
      System.out.println(a.toString()); 
     } 
    } 

} 

希望它可以幫助...

;-)

71

大家介紹的問題得到一個註釋,但問題在於您的註釋的定義。你應該添加到您的註釋定義一個@Retention(RetentionPolicy.RUNTIME)

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface MyAnnotation{ 
    int id(); 
} 
-2

或者你可以試試這個

try { 
    BeanInfo bi = Introspector.getBeanInfo(User.getClass()); 
    PropertyDescriptor[] properties = bi.getPropertyDescriptors(); 
    for(PropertyDescriptor property : properties) { 
     //One way 
     for(Annotation annotation : property.getAnnotations()){ 
      if(annotation instanceof Column) { 
       String string = annotation.name(); 
      } 
     } 
     //Other way 
     Annotation annotation = property.getAnnotation(Column.class); 
     String string = annotation.name(); 
    } 
}catch (IntrospectonException ie) { 
    ie.printStackTrace(); 
} 

希望這會有所幫助。

+6

我在Java 6或7中的'PropertyDescriptor'的API的任何地方都看不到'getAnnotations()'。我錯過了什麼嗎? http://docs.oracle.com/javase/7/docs/api/java/beans/PropertyDescriptor.html – 2014-03-04 16:34:51

+0

getReadMethod() – 2014-11-10 06:55:34

12

如果您需要知道是否存在特定的註釋。你可以這樣做:

Field[] fieldList = obj.getClass().getDeclaredFields(); 

     boolean isAnnotationNotNull, isAnnotationSize, isAnnotationNotEmpty; 

     for (Field field : fieldList) { 

      //Return the boolean value 
      isAnnotationNotNull = field.isAnnotationPresent(NotNull.class); 
      isAnnotationSize = field.isAnnotationPresent(Size.class); 
      isAnnotationNotEmpty = field.isAnnotationPresent(NotEmpty.class); 

     } 

等了其他註解:

我希望幫助別人。

0

我的方式

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.beans.BeanInfo; 
import java.beans.Introspector; 
import java.beans.PropertyDescriptor; 

public class ReadAnnotation { 
    private static final Logger LOGGER = LoggerFactory.getLogger(ReadAnnotation.class); 

    public static boolean hasIgnoreAnnotation(String fieldName, Class entity) throws NoSuchFieldException { 
     return entity.getDeclaredField(fieldName).isAnnotationPresent(IgnoreAnnotation.class); 
    } 

    public static boolean isSkip(PropertyDescriptor propertyDescriptor, Class entity) { 
     boolean isIgnoreField; 
     try { 
      isIgnoreField = hasIgnoreAnnotation(propertyDescriptor.getName(), entity); 
     } catch (NoSuchFieldException e) { 
      LOGGER.error("Can not check IgnoreAnnotation", e); 
      isIgnoreField = true; 
     } 
     return isIgnoreField; 
    } 

    public void testIsSkip() throws Exception { 
     Class<TestClass> entity = TestClass.class; 
     BeanInfo beanInfo = Introspector.getBeanInfo(entity); 

     for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { 
      System.out.printf("Field %s, has annotation %b", propertyDescriptor.getName(), isSkip(propertyDescriptor, entity)); 
     } 
    } 

}