2010-12-15 19 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, नहीं वर्ग पता के एनोटेशन (@Entity, @Table, @Cache)। उसकी प्राप्ति कैसे हो ? धन्यवाद।

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

@Bozho यह उपयोगी हो सकता है अगर आप डीबी वस्तुओं कॉपी, जैसा कि यहाँ मामला प्रतीत हो रहा है। प्रतिलिपि में एक ही आईडी नहीं हो सकती है, अगर इसे एक अलग डीबी इकाई बनना है। एक सामान्य प्रतिलिपि एल्गोरिदम एनोटेशन '@Id' के साथ कुछ भी बाहर कर सकता है। – Hok

उत्तर

61

यह कोड mkoryak का एक भिन्नता है, सिवाय इसके कि यह Class.newInstance (और यह संकलित) पर भरोसा नहीं करता है।

for(Field field : cls.getDeclaredFields()){ 
    Class type = field.getType(); 
    String name = field.getName(); 
    Annotation[] annotations = field.getDeclaredAnnotations(); 
} 

यह भी देखें: http://docs.oracle.com/javase/tutorial/reflect/class/classMembers.html

8

आप, प्रतिबिंब का उपयोग User वर्ग के सभी सदस्य खेतों पाने के लिए उन के माध्यम से पुनरावृति और उनके एनोटेशन

कुछ इस तरह खोजने के लिए:

propertyDescriptor.getReadMethod().getDeclaredAnnotations(); 

एक निजी क्षेत्र की टिप्पणियां प्राप्त करना एक बुरा विचार जैसा लगता है ... क्या होगा यदि संपत्ति को किसी क्षेत्र द्वारा समर्थित नहीं किया गया है, या है एक अलग नाम के साथ एक क्षेत्र द्वारा समर्थित? यहां तक ​​कि उन मामलों को अनदेखा करते हुए, आप निजी सामान को देखकर अमूर्त तोड़ रहे हैं।

+1

धन्यवाद, लेकिन मेरे क्लैज में कोई सार्वजनिक नो-एर्ग कन्स्ट्रक्टर नहीं है ... (क्षमा करें इसका उल्लेख नहीं किया गया है)। तो, clazz.newInstance() काम नहीं करेगा। – smallufo

+1

बस clazz.newInstance() लाइन को छोड़ दें, मुझे यकीन नहीं है कि क्यों mkoryak शामिल है - यह किसी भी चीज़ द्वारा उपयोग नहीं किया जाता है। – qualidafial

+1

ओह, मैंने कोड को सही में पेस्ट नहीं किया था। यह वास्तव में उपयोग किया जाता है – mkoryak

5

आप गेटर विधि पर भी टिप्पणियां प्राप्त कर सकते हैं:

+0

धन्यवाद, लेकिन अगर मैं कक्षा के कोड को संशोधित नहीं कर सकता तो क्या होगा? अगर मुझे निजी क्षेत्र की टिप्पणियां मिलनी हों तो क्या होगा? – smallufo

+0

@smallufo मैं वास्तव में जानना चाहता हूं कि आपको इसकी आवश्यकता क्यों है। यदि एनोटेशन निजी फ़ील्ड पर थे तो आप उनके बारे में जानना नहीं चाहते थे। –

+3

हाय, क्योंकि हमारे कोड बहुत सारे जेपीए के ट्यूटोरियल का पालन करते हैं। अधिकांश जेपीए ट्यूटोरियल/किताबें सीधे निजी क्षेत्रों में एनोटेशन जोड़ती हैं। और मैं जो खोदना चाहता हूं वह ये जेपीए एनोटेशन है। – smallufo

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

हर कोई समस्या का वर्णन करता एक प्राप्त करने के साथ nnotations, लेकिन समस्या आपकी एनोटेशन की परिभाषा में है। अगर आप अपनी टिप्पणी परिभाषा एक @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

मुझे जावा 6 या 7 में 'PropertyDescriptor' के लिए API में कहीं भी 'getAnotations()' नहीं दिखाई देता है। क्या मुझे कुछ याद आ रही है? http://docs.oracle.com/javase/7/docs/api/java/beans/PropertyDescriptor.html –

+0

getReadMethod() –

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

} 
संबंधित मुद्दे