解析 Hibernate Validator

任何获得Matrix授权的网站,转载请保留以下作者信息和链接:
作者:icess(作者的blog:http://blog.matrix.org.cn/page/icess)
关键字:Hibernate Validator

在前一篇文章 < Hibernate Validator 简介 > http://www.matrix.org.cn/resource/article/44/44153_Hibernate%20Validator%20.html中,我们看到了Hibernate Validator的使用方法,和自定义验证Annotation的实现以及错误消息的国际化等常见问题.

在使用如此优雅的属性验证框架的同时,你是否想了解她的细节呢?她究竟是怎么实现的呢? 那么现在就跟随我来探探她的内核吧!

Hibernate Validator 可以是一个独立的验证框架, 所以看完这篇分析 你可以把她独立出来作为你的个人验证框架来使用了 ^_^(如果你有兴趣和时间的话). Hibernate Validator 框架里面有两个主要的类: ClassValidator 和InvalidValue 还有一个接口Validator,在这三个主要的构件中 最主要的就只有一个 那就是ClassValidator.另外两个是很好理解的..

现在就让我们开始吧. 遵循由浅入深的习惯 我们先看看 Validator 接口吧. 其代码如下:

import  java.lang.annotation.Annotation;

/**
  * A constraint validator for a particular annotation
  *
  @author  Gavin King
  */
public interface  Validator<A  extends  Annotation> {
   /**
    * does the object/element pass the constraints
    */
   public boolean  isValid(Object value);

   /**
    * Take the annotations values
    @param  parameters
    */
   public void  initialize(A parameters);
}

Validator接口就是我们自定义约束的实现类要继承的接口,该接口在< Hibernate Validator 简介 > http://www.matrix.org.cn/resource/article/44/44153_Hibernate%20Validator%20.html 中已经讨论过了,请参考.

InvalidValue 类 大家看名字就应该可以猜到她的作用了吧. 她就是代表一个没有通过验证的错误实例.该类定义了一些方法,通过这些方法你可以取得与该Validator Annotation 有关的一些参数,如:她所注释的属性的值,错误消息等等. 该类的源代码如下:

import  java.io.Serializable;

/**
  * A single violation of a class level or method level constraint.
  *
  @author  Gavin King
  */
public class  InvalidValue  implements  Serializable {
   private final  String message;
   private final  Object value;
   private final  String propertyName;
   private final  Class beanClass;
   private final  Object bean;
   private  Object rootBean;

   public  Object getRootBean() {
     return  rootBean;
   }

   public  String getPropertyPath() {
     return  propertyPath;
   }

   private  String propertyPath;

   public  InvalidValue(String message, Class beanClass, String propertyName, Object value, Object bean) {
     this .message = message;
     this .value = value;
     this .beanClass = beanClass;
     this .propertyName = propertyName;
     this .bean = bean;
     this .rootBean = bean;
     this .propertyPath = propertyName;
   }

   public void  addParentBean(Object parentBean, String propertyName) {
     this .rootBean = parentBean;
     this .propertyPath = propertyName +  "."  this .propertyPath;
   }

   public  Class getBeanClass() {
     return  beanClass;
   }

   public  String getMessage() {
     return  message;
   }

   public  String getPropertyName() {
     return  propertyName;
   }

   public  Object getValue() {
     return  value;
   }

   public  Object getBean() {
     return  bean;
   }

   public  String toString() {
     return  propertyName +  ' '  + message;
   }

}

然后,就让我们看看最主要的类吧:ClassValidator . 该类代码有400余行,我都做了详细的注释如下:

import  该部分省略了;


/**
  * Engine that take a bean and check every expressed annotation restrictions
  *
  @author  Gavin King
  */
public class  ClassValidator<T>  implements  Serializable {
   private static  Log log = LogFactory.getLog( ClassValidator. class  );
   private static final  InvalidValue[] EMPTY_INVALID_VALUE_ARRAY =  new  InvalidValue[]{};
   private final  Class<T> beanClass;
   private transient  ResourceBundle messageBundle;
   private transient boolean  defaultResourceBundle;

   private final transient  Map<Class, ClassValidator> childClassValidators;
   private transient  List<Validator> beanValidators;
   private transient  List<Validator> memberValidators;
   private transient  List<Member> memberGetters;
   private transient  Map<Validator, String> messages;
   private transient  List<Member> childGetters;
   private static final  String DEFAULT_VALIDATOR_MESSAGE =  "org.hibernate.validator.resources.DefaultValidatorMessages" ;


   /**
    * create the validator engine for this bean type
    */
   public  ClassValidator(Class<T> beanClass) {
     this ( beanClass,  null  );
   }

   /**
    * create the validator engine for a particular bean class, using a resource bundle
    * for message rendering on violation
    */
   public  ClassValidator(Class<T> beanClass, ResourceBundle resourceBundle) {
     this ( beanClass, resourceBundle,  new  HashMap<Class, ClassValidator>() );
   }

   protected  ClassValidator(
       Class<T> beanClass, ResourceBundle resourceBundle, Map<Class, ClassValidator> childClassValidators
   ) {
     this .beanClass = beanClass;
     this .messageBundle = resourceBundle ==  null  ?
         getDefaultResourceBundle() :
         resourceBundle;
     this .childClassValidators = childClassValidators;
     initValidator( beanClass, childClassValidators,  this .messageBundle );  //重要的是该初始化函数
   }

   private  ResourceBundle getDefaultResourceBundle() {
     ResourceBundle rb;
     try  {
       rb = ResourceBundle.getBundle(  "ValidatorMessages"  );
     }
     catch ( MissingResourceException e) {
       //the user did not override the default ValidatorMessages
       log.debug(  "ResourceBundle ValidatorMessages not found. Delegate to "  + DEFAULT_VALIDATOR_MESSAGE);
       rb = ResourceBundle.getBundle( DEFAULT_VALIDATOR_MESSAGE );
     }
     defaultResourceBundle =  true ;
     return  rb;
   }

   private void  initValidator(
       Class<T> beanClass, Map<Class, ClassValidator> childClassValidators,
       ResourceBundle resourceBundle
   ) {
     beanValidators =  new  ArrayList<Validator>();  // 保存类级别的验证约束实现类
     memberValidators =  new  ArrayList<Validator>();  // 保存方法级别的验证约束实现类
     memberGetters =  new  ArrayList<Member>(); // 保存类的成员(字段or方法)和构造函数方法的标识信息
     messages =  new  HashMap<Validator, String>();  // 利用Map保存与每个Validator相对应的验证消息
     childGetters =  new  ArrayList<Member>(); //  保存子类的成员(字段or方法)和构造函数方法的标识信息

     childClassValidators.put( beanClass,  this  );  //map Map<Class, ClassValidator> childClassValidators;
     Annotation[] classAnnotations = beanClass.getAnnotations();
     for  int  i =  0 ; i < classAnnotations.length ; i++ ) {
       Annotation classAnnotation = classAnnotations[i];
      Validator beanValidator = createValidator( classAnnotation ); //根据Annotation来得到Validator,参考对该函数的解释
       if  ( beanValidator !=  null  ) beanValidators.add( beanValidator ); //保存该Validator
     }
     //build the class hierarchy to look for members in
     Collection<Class> classes =  new  HashSet<Class>();
     addSuperClassesAndInterfaces( beanClass, classes ); //把beanClass的所有超类和实现的接口添加的集合classes中

     //Check on all selected classes
     for  ( Class currClass : classes ) {
       Method[] methods = currClass.getDeclaredMethods(); // 扫描Method上面的注释
       for  int  i =  0 ; i < methods.length ; i++ ) {
         Method method = methods[i];
         createMemberValidator( method );  // 创建方法上的约束实现类(Validator), 参考对该函数的解释
         Class clazz = method.getReturnType(); // 得到该方法的返回类型
         createChildValidator( resourceBundle, method, clazz ); // 创建子类的Validator
       }

       Field[] fields = currClass.getDeclaredFields();  // 扫描Field上面的注释, 下面和上面Method的实现一样
       for  int  i =  0 ; i < fields.length ; i++ ) {
         Field field = fields[i];
         createMemberValidator( field );
         Class clazz = field.getType();
         createChildValidator( resourceBundle, field, clazz );
       }
     }
   }

   private void  addSuperClassesAndInterfaces(Class clazz, Collection<Class> classes) {
     for  ( Class currClass = clazz; currClass !=  null  ; currClass = currClass.getSuperclass() ) {
       if  ( ! classes.add( currClass ) )  return ;
       Class[] interfaces = currClass.getInterfaces();
       for  (Class interf : interfaces) {
         addSuperClassesAndInterfaces( interf, classes );
       }
     }
   }

   /**
    * 创建内嵌类的Validator. 如果该内嵌类被Valid Annotation 注释的话则 
    * 创建另外一个ClassValidator
    @param  resourceBundle
    @param  member
    @param  clazz
    */
   private void  createChildValidator(ResourceBundle resourceBundle, Member member, Class clazz) {
     if  ( ( (AnnotatedElement) member ).isAnnotationPresent( Valid. class  ) ) {
       setAccessible( member );
       childGetters.add( member );
       if  ( !childClassValidators.containsKey( clazz ) ) {
         new  ClassValidator( clazz, resourceBundle, childClassValidators );
       }
     }
   }

   /**
    * 利用传入的Method(实现了AnnotatedElement, GenericDeclaration, Member接口)
    * 得到 方法上的Annotations 然后利用私有方法createValidator(Annotation a)来创建
    * 每一个Annotation 的实现类 Validator 并保存Validator和member
    @param  member
    */
   private void  createMemberValidator(Member member) {
     Annotation[] memberAnnotations = ( (AnnotatedElement) member ).getAnnotations();
     for  int  j =  0 ; j < memberAnnotations.length ; j++ ) {
       Annotation methodAnnotation = memberAnnotations[j];
       Validator propertyValidator = createValidator( methodAnnotation );
       if  ( propertyValidator !=  null  ) {
         memberValidators.add( propertyValidator );
         setAccessible( member );  // 设置访问属性
         memberGetters.add( member );
       }
     }
   }

   private static void  setAccessible(Member member) {
     if  ( !Modifier.isPublic( member.getModifiers() ) ) {
       ( (AccessibleObject) member ).setAccessible(  true  );
     }
   }

   /**
    * 该方法产生了该Annotation的约束实现类 并初始化该类对应的消息
    */
   private  Validator createValidator(Annotation annotation) {
     try  {
       //得到ValidatorClass Annotation 
       ValidatorClass validatorClass = annotation.annotationType().getAnnotation( ValidatorClass. class  );
       if  ( validatorClass ==  null  ) {
         return null ;
       }
       // 然后 利用ValidatorClass Annotation 来得到里面的值(即实现该注释的Class),
       //再利用Class 构造一个instance
       Validator beanValidator = validatorClass.value().newInstance();
       beanValidator.initialize( annotation );  // 初始化Annotation中的参数(注意:在自定义约束中该方法有你来实现)
       String messageTemplate = (String) annotation.getClass()
           .getMethod(  "message" , (Class[])  null  )
           .invoke( annotation );   // 取得 constraint descriptor  中的message 的值
       String message = replace( messageTemplate, annotation );  // 初始化取得的模板消息 请参考 replace函数
       messages.put( beanValidator, message );  // 把message 放在map中,以便使用
       return  beanValidator;  // 返回 产生的Validator
     }
     catch  (Exception e) {
       throw new  IllegalArgumentException(  "could not instantiate ClassValidator" , e );
     }
   }

   public boolean  hasValidationRules() {
     return  beanValidators.size() !=  || memberValidators.size() !=  0 ;
   }

   /**
    * apply constraints on a bean instance and return all the failures.
    */
   public  InvalidValue[] getInvalidValues(T bean) {
     return this .getInvalidValues( bean,  new  IdentitySet() );
   }

   /**
    * apply constraints on a bean instance and return all the failures.
    */
   protected  InvalidValue[] getInvalidValues(T bean, Set<Object> circularityState) {
     if  ( circularityState.contains( bean ) ) {   // 该if else 是和Hibernate Core由关的,
       return  EMPTY_INVALID_VALUE_ARRAY;  //Avoid circularity
     }
     else  {
       circularityState.add( bean );
     }

     if  ( !beanClass.isInstance( bean ) ) {  // 如果beanClass不是该bean的实例,则抛出异常
       throw new  IllegalArgumentException(  "not an instance of: "  + bean.getClass() );
     }

     List<InvalidValue> results =  new  ArrayList<InvalidValue>();

     for  int  i =  0 ; i < beanValidators.size() ; i++ ) {  // 验证类级别的约束
       Validator validator = beanValidators.get( i );
       if  ( !validator.isValid( bean ) ) {  //调用isValid方法,如果没有通过则添加到list<InvalidValue>中
                         //如果是自定义约束则isValid方法 由你来实现
         results.add(  new  InvalidValue( messages.get( validator ), beanClass, null, bean, bean ) );
       }
     }

     for  int  i =  0 ; i < memberValidators.size() ; i++ ) { //验证方法级别的约束
       Member getter = memberGetters.get( i );
       if  Hibernate.isPropertyInitialized(bean, getter.getName() ) ) { // ? 检查该属性是否已初始化
         Object value = getMemberValue( bean, getter ); //利用反射 取得该属性的值
         Validator validator = memberValidators.get( i );  //取得该约束的验证实现类
         if  ( !validator.isValid( value ) ) { //调用isValid方法,如果没有通过则添加到list<InvalidValue>中
           String propertyName = getPropertyName( getter );
           results.add(  new  InvalidValue( messages.get( validator ), beanClass, propertyName, value, bean ) );
         }
       }
     }

     for  int  i =  0 ; i < childGetters.size() ; i++ ) { // 处理子类类
       Member getter = childGetters.get( i );
       if  Hibernate.isPropertyInitialized(bean, getter.getName() ) ) {  //检查该属性是否已初始化
         Object value = getMemberValue( bean, getter );
         if  ( value !=  null  && Hibernate.isInitialized( value ) ) {
           String propertyName = getPropertyName( getter );
           InvalidValue[] invalidValues = getClassValidator( value )
               .getInvalidValues( value, circularityState ); // 通过参数value 得到 Class, 然后由Class作为key          //在childClassValidators map中得到其ClassValidator
                                      //如果不存在 则创建新的 ,然后再调用ClassValidator的getInvalidValues方法
           // 注意在调用getInvalidValues方法时 用到了circularityState 参数, 当调用循环一周时 返回(递归结束)
           for  ( InvalidValue invalidValue : invalidValues ) {
             invalidValue.addParentBean( bean, propertyName );
             results.add( invalidValue );  //添加的结果中
           }
         }
       }
     }

     return  results.toArray(  new  InvalidValue[results.size()] );  //返回InvalidValue数组
   }

   /**
    * 通过参数value 得到 Class, 然后由Class作为key 在childClassValidators map中得到其ClassValidator
    * 如果不存在 则创建新的 然后返回
    @param  value
    @return
    */
   private  ClassValidator getClassValidator(Object value) {
     Class clazz = value.getClass();
     ClassValidator validator = childClassValidators.get( clazz );
     if  ( validator ==  null  ) {  //handles polymorphism
       validator =  new  ClassValidator( clazz );
     }
     return  validator;
   }

   /**
    * Apply constraints of a particular property on a bean instance and return all the failures.
    * Note this is not recursive.
    * 验证单个属性的约束.
    */
   //TODO should it be recursive ?
   public  InvalidValue[] getInvalidValues(T bean, String propertyName) {
     List<InvalidValue> results =  new  ArrayList<InvalidValue>();

     for  int  i =  0 ; i < memberValidators.size() ; i++ ) {
       Member getter = memberGetters.get( i );
       if  ( getPropertyName( getter ).equals( propertyName ) ) { // 验证该属性的约束
         Object value = getMemberValue( bean, getter );
         Validator validator = memberValidators.get( i );
         if  ( !validator.isValid( value ) ) {
           results.add(  new  InvalidValue( messages.get( validator ), beanClass, propertyName, value, bean ) );
         }
       }
     }

     return  results.toArray(  new  InvalidValue[results.size()] );
   }

   /**
    * Apply constraints of a particular property value of a bean type and return all the failures.
    * The InvalidValue objects returns return null for InvalidValue#getBean() and InvalidValue#getRootBean()
    * Note this is not recursive.
    * 验证 value 是否满足当前属性的约束.
    */
   //TODO should it be recursive?
   public  InvalidValue[] getPotentialInvalidValues(String propertyName, Object value) {
     List<InvalidValue> results =  new  ArrayList<InvalidValue>();

     for  int  i =  0 ; i < memberValidators.size() ; i++ ) {
       Member getter = memberGetters.get( i );
       if  ( getPropertyName( getter ).equals( propertyName ) ) {
         Validator validator = memberValidators.get( i );
         if  ( !validator.isValid( value ) ) {
           results.add(  new  InvalidValue( messages.get( validator ), beanClass, propertyName, value,  null  ) );
         }
       }
     }

     return  results.toArray(  new  InvalidValue[results.size()] );
   }

   private  Object getMemberValue(T bean, Member getter) {
     Object value;
     try  {
       value = getValue( getter, bean );
     }
     catch  (Exception e) {
       throw new  IllegalStateException(  "Could not get property value" , e );
     }
     return  value;
   }

   private  Object getValue(Member member, T bean)  throws  IllegalAccessException, InvocationTargetException {
     if  ( member  instanceof  Field ) {
       return  ( (Field) member ).get( bean );
     }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值