【问题标题】:How to get annotations of a member variable?如何获取成员变量的注释?
【发布时间】:2011-05-26 02:05:19
【问题描述】:

我想知道一个类的一些成员变量的注解,我用BeanInfo beanInfo = Introspector.getBeanInfo(User.class)自省一个类,用BeanInfo.getPropertyDescriptors()找到具体的属性,用Classtype = 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)。如何实现呢?谢谢。

【问题讨论】:

  • @Bozho 如果您复制数据库对象可能会很有用,就像这里的情况一样。如果它应该成为不同的数据库实体,则副本不能具有相同的 ID。通用复制算法可以排除带有注释“@Id”的任何内容。

标签: java reflection annotations beaninfo


【解决方案1】:
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

【讨论】:

    【解决方案2】:

    我的方式

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

    【讨论】:

      【解决方案3】:

      你必须使用反射来获取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
          }
      }
      

      【讨论】:

      • 谢谢,但我的 clazz 没有公共的无参数构造函数......(抱歉没有提到)。所以,clazz.newInstance() 将不起作用。
      • 只是省略 clazz.newInstance() 行,我不知道为什么 mkoryak 包含它——它没有被任何东西使用。
      • 对象没有任何方法getDeclaredFields。上课。
      【解决方案4】:

      如果您需要知道是否存在特定注释。你可以这样做:

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

      其他注解以此类推...

      我希望能帮助别人。

      【讨论】:

        【解决方案5】:

        或者你可以试试这个

        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】:

        每个人都描述了获取注释的问题,但问题在于注释的定义。您应该在注释定义中添加@Retention(RetentionPolicy.RUNTIME):

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

        【讨论】:

          【解决方案7】:
          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());
                  }
              }
          
          }
          

          希望对你有帮助...

          ;-)

          【讨论】:

            【解决方案8】:

            可以在getter方法上获取注解:

            propertyDescriptor.getReadMethod().getDeclaredAnnotations();
            

            获取私有字段的注释似乎是个坏主意...如果该属性甚至没有由字段支持,或者由具有不同名称的字段支持怎么办?即使忽略这些情况,您也会通过查看私有内容来打破抽象。

            【讨论】:

            • 谢谢,但是如果我不能修改课程的代码怎么办?如果我必须获取私有字段的注释怎么办?
            • @smallufo 我真的很想知道你为什么需要这个。如果注释是在私有字段上,那么您不应该知道它们。
            • 嗨,因为我们的代码遵循了很多 JPA 的教程。大多数 JPA 教程/书籍直接在私有字段中添加注释。而我要挖掘的是这些JPA注解。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-06-08
            • 1970-01-01
            • 2015-01-18
            • 1970-01-01
            • 2011-09-20
            相关资源
            最近更新 更多