2010-12-15 5 views
46

클래스의 멤버 변수의 주석을 알고 싶습니다. BeanInfo beanInfo = Introspector.getBeanInfo(User.class)을 사용하여 클래스를 검사하고 BeanInfo.getPropertyDescriptors()을 사용하여 특정 속성을 찾고 클래스 type = propertyDescriptor.getPropertyType()을 사용하여 속성의 클래스를 가져옵니다.멤버 변수의 주석을 얻는 방법은 무엇입니까?

하지만 멤버 변수에 주석을 추가하는 방법을 모르겠습니까?

나는 과 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

여기 경우 것 같다 당신이, DB 객체를 복사하면 그것은 유용 할 수 있습니다 @Bozho 내 방법. 복사본이 다른 DB 엔티티가되어야하는 경우 동일한 ID를 가질 수 없습니다. 일반 복사 알고리즘은 주석 '@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에는 public-no-arg 생성자가 없다 ... (미안하지만 언급하지 않았다.) 따라서 clazz.newInstance()는 작동하지 않습니다. – smallufo

+1

clazz.newInstance() 라인을 생략하면 mkoryak에 포함 된 이유가 확실하지 않습니다. 아무 것도 사용하지 않습니다. – qualidafial

+1

죄송합니다. 올바른 코드를 붙여 넣지 않았습니다. 실제로 사용됩니다 – mkoryak

5

당신은 getter 메소드에 주석을 얻을 수 있습니다 :

+0

감사합니다.하지만 클래스 코드를 수정할 수 없으면 어떻게해야합니까? 비공개 필드의 주석을 가져야하는 경우 어떻게해야합니까? – smallufo

+0

@smallufo 왜 이것이 필요한지 궁금합니다. 주석이 비공개 필드에있는 경우 사용자는 해당 주석을 알 수 없습니다. –

+3

안녕하세요. 코드가 JPA의 자습서를 많이 따르기 때문입니다. 대부분의 JPA 튜토리얼/책은 비공개 필드에 주석을 직접 추가합니다. 그리고 JPA 주석이 있습니다. – 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

모두이 문제에 대해 설명합니다 점점 주석이 있지만 문제는 주석의 정의에 있습니다. 당신은 당신의 주석 정의 @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 –

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

} 
관련 문제