从深处去掌握数据校验@Valid的作用(级联校验) (3)

这一步骤把该Bean上的字段、方法等等需要校验的项都提取出来。就拿上例中的Demo校验Person类来说,最终得出的BeanConfiguration如下:(两个)

在这里插入图片描述


在这里插入图片描述


这是直观的结论,可以看到仅仅是一个简单的类其实所包含的项是挺多的。

此处说一句:项是有这么多,但是并不是每一个都需要走验证逻辑的。因为毕竟大多数项上面并没有约束(注解),大多数ConstrainedElement.getConstraints()为空嘛~

总得来说,我个人建议不能光只记忆结论,因为那很容易忘记,所以还是得稍微深入一点,让记忆更深刻吧。那就从下面四个方面深入:

检索Field:getFieldMetaData( beanClass )

拿到本类所有字段Field:clazz.getDeclaredFields()

把每个Field都包装成ConstrainedElement存放起来~~~
1. 注意:此步骤完成了对每个Field上标注的注解进行了保存

检索Method:getMethodMetaData( beanClass )

拿到本类所有的方法Method:clazz.getDeclaredMethods()

排除掉静态方法和合成(isSynthetic)方法

把每个Method都转换成一个ConstrainedExecutable装着~~(ConstrainedExecutable也是个ConstrainedElement)。在此期间它完成了如下事(方法和构造器都复杂点,因为包含入参和返回值):
1. 找到方法上所有的注解保存起来
2. 处理入参、返回值(包括自动判断是作用在入参还是返回值上)

检索Constructor:getConstructorMetaData( beanClass )

完全同处理Method,略

检索Type:getClassLevelConstraints( beanClass )

找打标注在此类上的所有的注解,转换成ConstraintDescriptor

对已经找到每个ConstraintDescriptor进行处理,最终都转换Set<MetaConstraint<?>>这个类型
1.

把Set<MetaConstraint<?>>用一个ConstrainedType包装起来(ConstrainedType是个ConstrainedElement)

==关于级联校验此处补充说明一点,处理Type,都会处理级联校验情况,并且还是递归处理:==
也就是这个方法(课件@Valid在此处生效):

// type解释:分如下N中情况 // Field为:.getGenericType() // 字段的类型 // Method为:.getGenericReturnType() // 返回值类型 // Constructor:.getDeclaringClass() // 构造器所在类 // annotatedElement:可不一定说一定要有注解才能进来(每个字段、方法、构造器等都能传进来) private CascadingMetaDataBuilder getCascadingMetaData(Type type, AnnotatedElement annotatedElement, Map<TypeVariable<?>, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData) { return CascadingMetaDataBuilder.annotatedObject( type, annotatedElement.isAnnotationPresent( Valid.class ), containerElementTypesCascadingMetaData, getGroupConversions( annotatedElement ) ); }

这里对我们理解级联校验最重要的一句是:annotatedElement.isAnnotationPresent(Valid.class)。也就是说:若元素被此注解标注了,那就证明需要对它进行级联校验,这就是JSR定位@Valid的作用~

Spring提升了它???请关注后文Spring对它的应用吧~

ConstraintValidator.isValid()调用处

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywyjz.html