任何获得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 );
}