欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

解析 Hibernate Validator 博客分类: BlogJava HibernateBean框架J#Blog 

程序员文章站 2024-02-21 19:23:40
...

任何获得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() !=  0  || 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 );
     }
#fff