【问题标题】:Custom annotation not working for nested object field自定义注释不适用于嵌套对象字段
【发布时间】:2020-03-13 22:36:11
【问题描述】:

我创建了用于验证的小型自定义注释。如果该字段使用自定义注解进行注解,则会抛出异常。

下面是代码

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD})
public @interface NotRequired {
    public boolean value() default true;
}

型号::

public class Profile implements IProfile{
    @NotRequired
    private Integer id; 
    private String fName;    
    private IAddress add;
  //setter and getter

public class Address implements IAddress{
    @NotRequired
    private String address;

测试类::

public class CustomAnnotationTest {

    public static void main(String[] args) {
        IProfile profile = new Profile();      
        //profile.setId(123);  // in this case it is working fine
        IAddress address= new Address();
        address.setAddress("Aus"); // not working, expected exception should be thrown
        profile.setAdd(address);
        try {
            if (CustomAnnotationNotRequired.validateForNotRequirdField(profile)) {
               System.out.println("Validation Successful");
            }
        } catch (Exception e) {        
            e.printStackTrace();
        }
    }
}

验证器类:

public class CustomAnnotationNotRequired {
    public static boolean validateForNotRequirdField(Object objectToValidate)
            throws Exception {

        Field[] declaredFields = objectToValidate.getClass().getDeclaredFields();

        for(Field field : declaredFields) {

            Annotation annotation = field.getAnnotation(NotRequired.class);

            if (annotation != null) {

                NotRequired notRequired = (NotRequired) annotation;

                if (notRequired.value()) {
                     field.setAccessible(true); 
                     // annotated field is having value 
                     if (field.get(objectToValidate) != null) {
                         throw new Exception();
                     }
                }
            }
        }
        return true;
    }
}

测试用例: 1)

 IProfile profile = new Profile();     
        profile.setId(123); 

// 这个输入得到正确的结果

2)

IProfile profile = new Profile();      
            //profile.setId(123);
            IAddress address= new Address();
            address.setAddress("Aus");
            profile.setAdd(address);  

// 预期异常。Address 类的字段使用@NotRequired 注释进行了注释,但没有给出正确的结果。

【问题讨论】:

    标签: java validation nested inner-classes java-annotations


    【解决方案1】:

    验证不适用于address 字段,因为validateForNotRequirdField 方法仅验证profile 的字段,而不检查Address@NotRequired 注释。假设@NotRequired 只应用于一些常见的值类,对validateForNotRequirdField 方法的以下更改将产生预期的结果。

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.math.BigDecimal;
    import java.util.Date;
    
    public class CustomAnnotationNotRequired {
      public static boolean validateForNotRequirdField(Object objectToValidate)
          throws Exception {
    
        Field[] declaredFields = objectToValidate.getClass().getDeclaredFields();
    
        for (Field field : declaredFields) {
    
          Annotation annotation = field.getAnnotation(NotRequired.class);
          if (!isValueClass(field.getType())) {
            field.setAccessible(true);
            if (field.get(objectToValidate) != null) {
              // validate nested field
              validateForNotRequirdField(field.get(objectToValidate));
            }
            continue;
          }
          if (annotation != null) {
    
            NotRequired notRequired = (NotRequired) annotation;
    
            if (notRequired.value()) {
              field.setAccessible(true);
              // annotated field is having value
              if (field.get(objectToValidate) != null) {
                throw new Exception();
              }
            }
          }
        }
        return true;
      }
    
      private static boolean isValueClass(Class<?> fieldType) {
        // Add other class if needed.
        return fieldType.equals(String.class) || fieldType.equals(Integer.class)
               || fieldType.equals(Short.class) || fieldType.equals(Long.class)
               || fieldType.equals(BigDecimal.class)
               || fieldType.equals(Date.class);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-08
      • 2018-02-06
      • 2020-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多