解析 Hibernate Validator 博客分类: BlogJava HibernateBean框架J#Blog
任何获得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