Spring validation参数校验系列
1、Spring validation参数校验基本使用
2、Spring validation参数校验之自定义校验规则及编程式校验等进阶篇
3、【源码】Spring validation参数校验原理解析之Controller控制器参数校验中@RequestBody参数校验实现原理
4、【源码】Spring validation参数校验原理解析之Controller控制器参数校验中@ModelAttribute及实体类参数校验实现原理
5、【源码】Spring validation参数校验原理解析之基本类型参数及Service层方法参数校验实现原理
6、【源码】Spring validation校验的核心类ValidatorImpl、MetaDataProvider和AnnotationMetaDataProvider源码分析
7、Spring validation参数校验高级篇之跨参数校验Cross-Parameter及分组序列校验@GroupSequenceProvider、@GroupSequence
8、【源码】Spring validation参数校验之跨参数校验Cross-Parameter原理分析
9、【源码】Spring validation参数校验之分组序列校验@GroupSequenceProvider、@GroupSequence的实现原理
10、【源码】Spring validation参数校验实现原理总结
前言
本篇继续从源码的角度分析一下Spring validation参数校验的分组序列校验@GroupSequenceProvider、@GroupSequence的实现原理。
温馨提醒:
Hibernate validation的设计比较复杂,要一次性全部分析清楚很困难,关联的细节很多。所以《Spring validation参数校验系列》文章通过从整体到细节,在每一篇中,不影响主题内容的情况下,穿插引入一些细节。在分享中,也会暂时忽略一些细节,留在下一篇讲解。建议如果本篇不太理解的,可以看看该系列的上一篇或者下一篇源码讲解文章。
一、解析分组序列
类中添加的约束元数据信息首次解析是在BeanMetaDataManagerImpl的createBeanMetaData()方法中调用。首次解析调用流程详见
【源码】Spring validation参数校验原理解析之Controller控制器参数校验中@RequestBody参数校验实现原理_@requestbody 校验字段-CSDN博客
的ValidatorImpl.validate()部分。入口方法为BeanMetaDataManagerImpl的createBeanMetaData()方法。
private <T> BeanMetaDataImpl<T> createBeanMetaData(Class<T> clazz) {
BeanMetaDataBuilder<T> builder = BeanMetaDataBuilder.getInstance(
constraintCreationContext, executableHelper, parameterNameProvider,
validationOrderGenerator, clazz, methodValidationConfiguration );
for ( MetaDataProvider provider : metaDataProviders ) {
// getBeanConfigurationForHierarchy()方法遍历beanClass及其父类,调用AnnotaionMetaDataProvider.getBeanConfiguration()方法
// 获取对应类添加的约束注解,封装成BeanConfiguration对象
for ( BeanConfiguration<? super T> beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) {
// 在BeanMetaDataBuilder中添加BeanConfiguration对象
// BeanMetaDataBuilder.add()【获取并遍历约束元素,获取beanConfiguration中的sequenceSource
// 和defaultGroupSequence保存到builder中
builder.add( beanConfiguration );
}
}
// 将类中添加的约束信息封装成BeanMetaDataImpl对象。
return builder.build();
}
1.1 AnnotationMetaDataProvider的getBeanConfiguration()方法解析类中的方法、属性、构造器添加的约束注解。
public class AnnotationMetaDataProvider implements MetaDataProvider {
/**
* 获取bean类中定义的属性、类、参数、方法添加的约束信息、配置来源、分组序列以及动态分组序列程序
*/
@Override
@SuppressWarnings("unchecked")
public <T> BeanConfiguration<T> getBeanConfiguration(Class<T> beanClass) {
if ( Object.class.equals( beanClass ) ) {
return (BeanConfiguration<T>) objectBeanConfiguration;
}
return retrieveBeanConfiguration( beanClass );
}
/**
* 检索bean类的元数据信息
*/
private <T> BeanConfiguration<T> retrieveBeanConfiguration(Class<T> beanClass) {
// 获取类中定义的属性添加的约束元素信息
Set<ConstrainedElement> constrainedElements = getFieldMetaData( beanClass );
// 获取类中定义的方法添加的约束元素信息
constrainedElements.addAll( getMethodMetaData( beanClass ) );
// 获取类的构造方法添加的约束元素信息
constrainedElements.addAll( getConstructorMetaData( beanClass ) );
// 获取类级添加的约束信息
Set<MetaConstraint<?>> classLevelConstraints = getClassLevelConstraints( beanClass );
if ( !classLevelConstraints.isEmpty() ) {
ConstrainedType classLevelMetaData =
new ConstrainedType(
ConfigurationSource.ANNOTATION,
beanClass,
classLevelConstraints
);
constrainedElements.add( classLevelMetaData );
}
// 封装成BeanConfiguration对象,来源为Annotation
return new BeanConfiguration<>(
ConfigurationSource.ANNOTATION,
beanClass,
constrainedElements,
// 获取bean中添加的@GroupSequence注解的组序列。
getDefaultGroupSequence( beanClass ),
// 获取类中定义的动态分组的约定程序
getDefaultGroupSequenceProvider( beanClass )
);
}
/**
* 获取bean中添加的@GroupSequence注解的组序列。组序列中的组顺序执行,排前面的组对应的注解约束会先判断,如果前面的失败了,不会校验排后面的组
* @param beanClass
* @return
*/
private List<Class<?>> getDefaultGroupSequence(Class<?> beanClass) {
GroupSequence groupSequenceAnnotation = beanClass.getAnnotation( GroupSequence.class );
return groupSequenceAnnotation != null ? Arrays.asList( groupSequenceAnnotation.value() ) : null;
}
/**
* 获取类中定义的动态分组的约定程序
* @param beanClass
* @param <T>
* @return
*/
private <T> DefaultGroupSequenceProvider<? super T> getDefaultGroupSequenceProvider(Class<T> beanClass) {
// 判断对应的bean是否添加了GroupSequenceProvider注解
GroupSequenceProvider groupSequenceProviderAnnotation = beanClass.getAnnotation( GroupSequenceProvider.class );
// 只有添加了GroupSequenceProvider注解才会返回动态分组的约定程序
if ( groupSequenceProviderAnnotation != null ) {
// 获取GroupSequenceProvider注解中指定的约定程序类,该类实现了DefaultGroupSequenceProvider接口
@SuppressWarnings("unchecked")
Class<? extends DefaultGroupSequenceProvider<? super T>> providerClass =
(Class<? extends DefaultGroupSequenceProvider<? super T>>) groupSequenceProviderAnnotation.value();
// 创建一个自定义的DefaultGroupSequenceProvider实例
return newGroupSequenceProviderClassInstance( beanClass, providerClass );
}
return null;
}
/**
* 创建一个DefaultGroupSequenceProvider实例,getValidationGroups()方法的参数必现是beanClass类型
* @param beanClass
* @param providerClass
* @param <T>
* @return
*/
private <T> DefaultGroupSequenceProvider<? super T> newGroupSequenceProviderClassInstance(Class<T> beanClass,
Class<? extends DefaultGroupSequenceProvider<? super T>> providerClass) {
Method[] providerMethods = run( GetMethods.action( providerClass ) );
for ( Method method : providerMethods ) {
Class<?>[] paramTypes = method.getParameterTypes();
// 判断DefaultGroupSequenceProvider接口的getValidationGroups()方法的参数是否为beanClass类型
if ( "getValidationGroups".equals( method.getName() ) && !method.isBridge()
&& paramTypes.length == 1 && paramTypes[0].isAssignableFrom( beanClass ) ) {
return run(
NewInstance.action( providerClass, "the default group sequence provider" )
);
}
}
throw LOG.getWrongDefaultGroupSequenceProviderTypeException( beanClass );
}
}
在retrieveBeanConfiguration()方法中,会调用getDefaultGroupSequence()和getDefaultGroupSequenceProvider()分别解析@GroupSequence和@GroupSequenceProvider注解的分组序列及自定义的DefaultGroupSequenceProvider对象,并保存到BeanConfiguration中。
1.2 通过BeanMetaDataBuilder.add(beanConfiguration)方法中,获取约束元素,获取beanConfiguration中的sequenceSource和defaultGroupSequence保存到builder中。
1.3 执行builder.build(),new一个BeanMetaDataImpl对象,将类中添加的约束信息封装成BeanMetaDataImpl对象。在BeanMetaDataImpl的构造方法中,对分组系列及动态分组系列程序进行解析处理。
/**
* defaultGroupSequence:分组序列组。在AnnotaionMetaDataProvider.getDefaultGroupSequence()方法中获取,
* 如果没有设置@GroupSequence,则该值为null
* defaultGroupSequenceProvider:动态分组约定程序,自定义的DefaultGroupSequenceProvider对象。
* 在defaultGroupSequence:分组序列组。在AnnotaionMetaDataProvider.getDefaultGroupSequenceProvider()中获取,如果没有为null
* constraintMetaDataSet:类及父类的所有属性、构造器、方法添加的约束元数据
*/
public BeanMetaDataImpl(Class<T> beanClass,
List<Class<?>> defaultGroupSequence,
DefaultGroupSequenceProvider<? super T> defaultGroupSequenceProvider,
Set<ConstraintMetaData> constraintMetaDataSet,
ValidationOrderGenerator validationOrderGenerator) {
// 保存基础信息
this.validationOrderGenerator = validationOrderGenerator;
this.beanClass = beanClass;
this.propertyMetaDataMap = newHashMap();
Set<PropertyMetaData> propertyMetaDataSet = newHashSet();
Set<ExecutableMetaData> executableMetaDataSet = newHashSet();
Set<Signature> tmpUnconstrainedExecutables = newHashSet();
boolean hasConstraints = false;
Set<MetaConstraint<?>> allMetaConstraints = newHashSet();
// 对constraintMetaDataSet进行分类,分成属性、类、方法
for ( ConstraintMetaData constraintMetaData : constraintMetaDataSet ) {
boolean elementHasConstraints = constraintMetaData.isCascading() || constraintMetaData.isConstrained();
hasConstraints |= elementHasConstraints;
// 属性添加的约束
if ( constraintMetaData.getKind() == ElementKind.PROPERTY ) {
propertyMetaDataSet.add( (PropertyMetaData) constraintMetaData );
}
// 类添加的约束
else if ( constraintMetaData.getKind() == ElementKind.BEAN ) {
allMetaConstraints.addAll( ( (ClassMetaData) constraintMetaData ).getAllConstraints() );
}
else {
// 方法添加的约束
ExecutableMetaData executableMetaData = (ExecutableMetaData) constraintMetaData;
if ( elementHasConstraints ) {
executableMetaDataSet.add( executableMetaData );
}
else {
tmpUnconstrainedExecutables.addAll( executableMetaData.getSignatures() );
}
}
}
// 级联
Set<Cascadable> cascadedProperties = newHashSet();
for ( PropertyMetaData propertyMetaData : propertyMetaDataSet ) {
propertyMetaDataMap.put( propertyMetaData.getName(), propertyMetaData );
cascadedProperties.addAll( propertyMetaData.getCascadables() );
allMetaConstraints.addAll( propertyMetaData.getAllConstraints() );
}
this.hasConstraints = hasConstraints;
this.cascadedProperties = CollectionHelper.toImmutableSet( cascadedProperties );
this.allMetaConstraints = CollectionHelper.toImmutableSet( allMetaConstraints );
this.classHierarchyWithoutInterfaces = CollectionHelper.toImmutableList( ClassHierarchyHelper.getHierarchy(
beanClass,
Filters.excludeInterfaces()
) );
// 转换并将分组序列信息存放在分组序列上下文中
DefaultGroupSequenceContext<? super T> defaultGroupContext = getDefaultGroupSequenceData( beanClass, defaultGroupSequence, defaultGroupSequenceProvider, validationOrderGenerator );
this.defaultGroupSequenceProvider = defaultGroupContext.defaultGroupSequenceProvider;
this.defaultGroupSequence = CollectionHelper.toImmutableList( defaultGroupContext.defaultGroupSequence );
this.validationOrder = defaultGroupContext.validationOrder;
this.directMetaConstraints = getDirectConstraints();
this.executableMetaDataMap = CollectionHelper.toImmutableMap( bySignature( executableMetaDataSet ) );
this.unconstrainedExecutables = CollectionHelper.toImmutableSet( tmpUnconstrainedExecutables );
// 如果有通过@GroupSequence添加序列组或定义DefaultGroupSequenceProvider,
// 则defaultGroupSequenceRedefined为true
this.defaultGroupSequenceRedefined = this.defaultGroupSequence.size() > 1 || hasDefaultGroupSequenceProvider();
// 如果有动态分组序列,执行DefaultGroupSequenceProvider的getValidationGroups()方法获取分组,否则返回null
// 由于此处传入getValidationGroups()的值为null,所以在自定义的DefaultGroupSequenceProvider
// 类的getValidationGroups()方法要对参数进行判空处理
this.resolvedDefaultGroupSequence = getDefaultGroupSequence( null );
}
/**
* 转换并将分组序列信息存放在分组序列上下文中
*/
private static <T> DefaultGroupSequenceContext<T> getDefaultGroupSequenceData(Class<?> beanClass, List<Class<?>> defaultGroupSequence, DefaultGroupSequenceProvider<? super T> defaultGroupSequenceProvider, ValidationOrderGenerator validationOrderGenerator) {
if ( defaultGroupSequence != null && defaultGroupSequenceProvider != null ) {
throw LOG.getInvalidDefaultGroupSequenceDefinitionException();
}
DefaultGroupSequenceContext<T> context = new DefaultGroupSequenceContext<>();
// 如果有动态分组序列,则分组序列defaultGroupSequence标记为空,不考虑校验顺序
if ( defaultGroupSequenceProvider != null ) {
context.defaultGroupSequenceProvider = defaultGroupSequenceProvider;
context.defaultGroupSequence = Collections.emptyList();
context.validationOrder = null;
}
// 否则的话,如果有分组系列,解析获取分组系列
else if ( defaultGroupSequence != null && !defaultGroupSequence.isEmpty() ) {
context.defaultGroupSequence = getValidDefaultGroupSequence( beanClass, defaultGroupSequence );
context.validationOrder = validationOrderGenerator.getDefaultValidationOrder( beanClass, context.defaultGroupSequence );
}
else {
// 使用默认分组
context.defaultGroupSequence = DEFAULT_GROUP_SEQUENCE;
context.validationOrder = ValidationOrder.DEFAULT_SEQUENCE;
}
return context;
}
/**
* 获取分组序列。必须添加beanClass类作为分组中的元素,且会转换为Default分组
*/
private static List<Class<?>> getValidDefaultGroupSequence(Class<?> beanClass, List<Class<?>> groupSequence) {
List<Class<?>> validDefaultGroupSequence = new ArrayList<>();
boolean groupSequenceContainsDefault = false;
if ( groupSequence != null ) {
for ( Class<?> group : groupSequence ) {
// 如果分组序列中存在类名的分组,则添加Default分组,且groupSequenceContainsDefault为true
if ( group.getName().equals( beanClass.getName() ) ) {
validDefaultGroupSequence.add( Default.class );
groupSequenceContainsDefault = true;
}
// 如果在分组系列中添加了Default分组,则抛异常
else if ( group.getName().equals( Default.class.getName() ) ) {
throw LOG.getNoDefaultGroupInGroupSequenceException();
}
else {
// 添加分组
validDefaultGroupSequence.add( group );
}
}
}
// 如果groupSequenceContainsDefault为false,即在分组序列中没有添加对应类名的分组,则抛异常
if ( !groupSequenceContainsDefault ) {
throw LOG.getBeanClassMustBePartOfRedefinedDefaultGroupSequenceException( beanClass );
}
if ( LOG.isTraceEnabled() ) {
LOG.tracef(
"Members of the default group sequence for bean %s are: %s.",
beanClass.getName(),
validDefaultGroupSequence
);
}
return validDefaultGroupSequence;
}
/**
* 如果有动态分组序列,执行DefaultGroupSequenceProvider的getValidationGroups()方法获取分组,否则返回分组系列
*/
@Override
public List<Class<?>> getDefaultGroupSequence(T beanState) {
if ( hasDefaultGroupSequenceProvider() ) {
List<Class<?>> providerDefaultGroupSequence = defaultGroupSequenceProvider.getValidationGroups( beanState );
return getValidDefaultGroupSequence( beanClass, providerDefaultGroupSequence );
}
return defaultGroupSequence;
}
/**
* 获取当前beanClass的分组序列。如果定义了DefaultGroupSequenceProvider,则执行getValidationGroups(),获得动态分组序列Sequence集合
*/
@Override
public Iterator<Sequence> getDefaultValidationSequence(T beanState) {
// 如果有动态分组序列
if ( hasDefaultGroupSequenceProvider() ) {
// 执行DefaultGroupSequenceProvider的getValidationGroups(),获取动态分组序列
List<Class<?>> providerDefaultGroupSequence = defaultGroupSequenceProvider.getValidationGroups( beanState );
return validationOrderGenerator.getDefaultValidationOrder(
beanClass,
// 获取分组序列。必须添加类名的分组,且会转换为Default分组。此处说明在自定义
// 的DefaultGroupSequenceProvider.getValidationGroups()方法中返回的分组序列也必须包含beanClass类作为分组
getValidDefaultGroupSequence( beanClass, providerDefaultGroupSequence )
)
.getSequenceIterator();
}
else {
return validationOrder.getSequenceIterator();
}
}
}
注:通过构造器的最后一行代码调用了getDefaultGroupSequence(null),传入的值为null。如果有动态分组程序,该方法会执行DefaultGroupSequenceProvider.getValidationGroups(),且传入null,所以要在该方法中进行判空处理。另外,结合getValidDefaultGroupSequence()方法的代码,在使用@GroupSequence时,需要添加beanClass的分组作为默认分组,该方法会自动转换为Default分组。
二、分组序列校验
validation校验的时候,会调用ValidatorImol的validate()或validateXXX()方法,不明白的可以看前面的博文。ValidatorImol.validate()代码如下:
@Override
public final <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
sanityCheckGroups( groups );
@SuppressWarnings("unchecked")
Class<T> rootBeanClass = (Class<T>) object.getClass();
// 从BeanMetaDataManager中获取类对应的BeanMetaData对象,为BeanMetaDataImpl实例
BeanMetaData<T> rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );
if ( !rootBeanMetaData.hasConstraints() ) {
return Collections.emptySet();
}
BaseBeanValidationContext<T> validationContext = getValidationContextBuilder().forValidate( rootBeanClass, rootBeanMetaData, object );
// 确定组验证顺序
ValidationOrder validationOrder = determineGroupValidationOrder( groups );
BeanValueContext<?, Object> valueContext = ValueContexts.getLocalExecutionContextForBean(
validatorScopedContext.getParameterNameProvider(),
object,
validationContext.getRootBeanMetaData(),
PathImpl.createRootPath()
);
// 验证
return validateInContext( validationContext, valueContext, validationOrder );
}
private ValidationOrder determineGroupValidationOrder(Class<?>[] groups) {
Collection<Class<?>> resultGroups;
// 没有添加分组的话,默认为Default分组
if ( groups.length == 0 ) {
resultGroups = DEFAULT_GROUPS;
}
else {
resultGroups = Arrays.asList( groups );
}
// 获取验证组顺序
return validationOrderGenerator.getValidationOrder( resultGroups );
}
2.1 在该方法中,先从BeanMetaDataManager中获取类对应的BeanMetaData对象,及上面1.3中讲解的BeanMetaDataImpl对象。
2.2 然后执行determineGroupValidationOrder(Class<?>[] groups),其中的groups为validate()方法中传入的,为@Validated注解中添加的,默认为Default分组。该方法调用validationOrderGenerator.getValidationOrder( resultGroups )获取分组顺序。
public class ValidationOrderGenerator {
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
private final ConcurrentMap<Class<?>, Sequence> resolvedSequences = new ConcurrentHashMap<Class<?>, Sequence>();
/**
* 为指定的验证组生成组和序列的顺序,返回验证的执行顺序对象ValidationOrder
*/
public ValidationOrder getValidationOrder(Collection<Class<?>> groups) {
// 必须有分组
if ( groups == null || groups.size() == 0 ) {
throw LOG.getAtLeastOneGroupHasToBeSpecifiedException();
}
// 如果只有Default.class分组,返回默认分组顺序
if ( groups.size() == 1 && groups.contains( Default.class ) ) {
return ValidationOrder.DEFAULT_GROUP;
}
// 分组必须的接口
for ( Class<?> clazz : groups ) {
if ( !clazz.isInterface() ) {
throw LOG.getGroupHasToBeAnInterfaceException( clazz );
}
}
DefaultValidationOrder validationOrder = new DefaultValidationOrder();
// 遍历分组
for ( Class<?> clazz : groups ) {
if ( Default.class.equals( clazz ) ) { // HV-621
validationOrder.insertGroup( Group.DEFAULT_GROUP );
}
// 如果分组中添加了@GroupSequence注解
else if ( isGroupSequence( clazz ) ) {
insertSequence( clazz, clazz.getAnnotation( GroupSequence.class ).value(), true, validationOrder );
}
else {
Group group = new Group( clazz );
// 将分组添加到validationOrder,在validationOrder对象中,使用List<Group>存放
validationOrder.insertGroup( group );
// 将继承的组递归添加到组链List<Group>中
insertInheritedGroups( clazz, validationOrder );
}
}
return validationOrder;
}
/**
* 获取验证顺序。将defaultGroupSequence中的分组和clazz组成Sequence,添加到ValidationOrder
*/
public ValidationOrder getDefaultValidationOrder(Class<?> clazz, List<Class<?>> defaultGroupSequence) {
// 定义一个DefaultValidationOrder对象
DefaultValidationOrder validationOrder = new DefaultValidationOrder();
// 以clazz为单位【当前分组类】,记录分组序列中的分组,封装成Sequence对象,保存到validationOrder中
insertSequence( clazz, defaultGroupSequence.toArray( new Class<?>[defaultGroupSequence.size()] ), false, validationOrder );
return validationOrder;
}
private boolean isGroupSequence(Class<?> clazz) {
return clazz.getAnnotation( GroupSequence.class ) != null;
}
/**
* 将继承的组递归添加到组链中
*/
private void insertInheritedGroups(Class<?> clazz, DefaultValidationOrder chain) {
for ( Class<?> inheritedGroup : clazz.getInterfaces() ) {
Group group = new Group( inheritedGroup );
chain.insertGroup( group );
insertInheritedGroups( inheritedGroup, chain );
}
}
/**
* 以sequenceClass为单位,记录分组序列中的分组,封装成Sequence对象,保存到validationOrder中
*/
private void insertSequence(Class<?> sequenceClass, Class<?>[] sequenceElements, boolean cache, DefaultValidationOrder validationOrder) {
// 如果是@GroupSequence注解中的分组序列,cache为true,会进行缓存
Sequence sequence = cache ? resolvedSequences.get( sequenceClass ) : null;
if ( sequence == null ) {
// 解析sequenceClass中的所有分组系列,如果分组系列中的分组还有@GroupSequence,递归调用,全部添加到ArrayList中
sequence = resolveSequence( sequenceClass, sequenceElements, new ArrayList<Class<?>>() );
// 只有在确定序列是否可扩展后,才能扩展继承的组
sequence.expandInheritedGroups();
// 缓存
if ( cache ) {
final Sequence cachedResolvedSequence = resolvedSequences.putIfAbsent( sequenceClass, sequence );
if ( cachedResolvedSequence != null ) {
sequence = cachedResolvedSequence;
}
}
}
// 添加到validationOrder的Map属性中,key为分组类名称,value为分组类中添加的@GroupSequence分组
validationOrder.insertSequence( sequence );
}
/**
* 遍历sequenceClass分组中的@GroupSequence分组sequenceElements到List中,封装成Sequence对象。如果分组中还有@GroupSequence,则递归调用
*/
private Sequence resolveSequence(Class<?> sequenceClass, Class<?>[] sequenceElements, List<Class<?>> processedSequences) {
// 如果sequenceClass分组已经处理了,则抛异常
if ( processedSequences.contains( sequenceClass ) ) {
throw LOG.getCyclicDependencyInGroupsDefinitionException();
}
else {
// 将sequenceClass分组添加到已处理集合中
processedSequences.add( sequenceClass );
}
List<Group> resolvedSequenceGroups = new ArrayList<Group>();
// 遍历分组序列中的分组
for ( Class<?> clazz : sequenceElements ) {
// 继续判断对应的分组添加了@GroupSequence,则递归遍历@GroupSequence中的分组序列
if ( isGroupSequence( clazz ) ) {
Sequence tmpSequence = resolveSequence( clazz, clazz.getAnnotation( GroupSequence.class ).value(), processedSequences );
// 将分组中添加的@GroupSequence序列分组信息添加到resolvedSequenceGroups中
addGroups( resolvedSequenceGroups, tmpSequence.getComposingGroups() );
}
else {
List<Group> list = new ArrayList<Group>();
list.add( new Group( clazz ) );
// 将分组添加到resolvedSequenceGroups中
addGroups( resolvedSequenceGroups, list );
}
}
return new Sequence( sequenceClass, resolvedSequenceGroups );
}
/**
* 将groups中的分组信息添加到resolvedGroupSequence中
*/
private void addGroups(List<Group> resolvedGroupSequence, List<Group> groups) {
for ( Group tmpGroup : groups ) {
if ( resolvedGroupSequence.contains( tmpGroup ) && resolvedGroupSequence.indexOf( tmpGroup ) < resolvedGroupSequence
.size() - 1 ) {
throw LOG.getUnableToExpandGroupSequenceException();
}
resolvedGroupSequence.add( tmpGroup );
}
}
}
如果分组添加了@GroupSequence,则会遍历分组序列,如果分组序列的分组还添加了@GroupSequence,会循环递归遍历。解析所有的分组,封装成Sequence对象。保存到ValidationOrder对象中。
注:在自定义的DefaultGroupSequenceProvider.getValidationGroups()方法中,返回的分组数组必须包含beanClass作为分组
2.3 执行validateInContext()方法
public class ValidatorImpl implements Validator, ExecutableValidator {
private <T, U> Set<ConstraintViolation<T>> validateInContext(BaseBeanValidationContext<T> validationContext, BeanValueContext<U, Object> valueContext,
ValidationOrder validationOrder) {
if ( valueContext.getCurrentBean() == null ) {
return Collections.emptySet();
}
BeanMetaData<U> beanMetaData = valueContext.getCurrentBeanMetaData();
// 判断当前bean是否添加了@DefaultGroupSequence
if ( beanMetaData.isDefaultGroupSequenceRedefined() ) {
// 先执行beanMetaData.getDefaultGroupSequence(valueContext.getCurrentBean()),此时传入了实体对象。
// 如果有动态分组系列程序DefaultGroupSequenceProvider,则会再次执行
// DefaultGroupSequenceProvider.getValidationGroups()方法,动态获取分组。
// validationOrder.assertDefaultGroupSequenceIsExpandable()默认为空方法
validationOrder.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence( valueContext.getCurrentBean() ) );
}
// 处理第一个单组。对于这些,可以通过在遍历对象之前首先在当前bean上运行所有验证来优化对象遍历
Iterator<Group> groupIterator = validationOrder.getGroupIterator();
// 遍历分组
while ( groupIterator.hasNext() ) {
Group group = groupIterator.next();
// 设置当前执行的分组
valueContext.setCurrentGroup( group.getDefiningClass() );
// 执行校验
validateConstraintsForCurrentGroup( validationContext, valueContext );
if ( shouldFailFast( validationContext ) ) {
return validationContext.getFailingConstraints();
}
}
groupIterator = validationOrder.getGroupIterator();
// 遍历分组
while ( groupIterator.hasNext() ) {
Group group = groupIterator.next();
// 设置当前执行的分组
valueContext.setCurrentGroup( group.getDefiningClass() );
// 执行级联校验
validateCascadedConstraints( validationContext, valueContext );
if ( shouldFailFast( validationContext ) ) {
return validationContext.getFailingConstraints();
}
}
// 处理分组序列。对于序列,必须遍历对象图,因为当发生错误时,必须停止处理。
// 获取分组序列集合,并遍历Sequence
Iterator<Sequence> sequenceIterator = validationOrder.getSequenceIterator();
while ( sequenceIterator.hasNext() ) {
Sequence sequence = sequenceIterator.next();
// 遍历sequence中的扩展组,一组系列分组会存放在一个扩展组中。此处感觉有些多余
for ( GroupWithInheritance groupOfGroups : sequence ) {
int numberOfViolations = validationContext.getFailingConstraints().size();
// 遍历组
for ( Group group : groupOfGroups ) {
// 设置当前分组
valueContext.setCurrentGroup( group.getDefiningClass() );
// 执行校验
validateConstraintsForCurrentGroup( validationContext, valueContext );
if ( shouldFailFast( validationContext ) ) {
return validationContext.getFailingConstraints();
}
// 执行级联校验
validateCascadedConstraints( validationContext, valueContext );
if ( shouldFailFast( validationContext ) ) {
return validationContext.getFailingConstraints();
}
}
if ( validationContext.getFailingConstraints().size() > numberOfViolations ) {
break;
}
}
}
// 校验上下文的错误消息,所有的校验注解之间的上下文ConstraintValidatorContext是完全独立的,无法互相访问通信
return validationContext.getFailingConstraints();
}
private void validateConstraintsForCurrentGroup(BaseBeanValidationContext<?> validationContext, BeanValueContext<?, Object> valueContext) {
// 如果不是Default默认组,调用validateConstraintsForNonDefaultGroup(),直接进行验证
if ( !valueContext.validatingDefault() ) {
validateConstraintsForNonDefaultGroup( validationContext, valueContext );
}
// 如果是验证默认组序列,需要考虑层次结构中的类可以重新定义默认组序列
else {
validateConstraintsForDefaultGroup( validationContext, valueContext );
}
}
private <U> void validateConstraintsForDefaultGroup(BaseBeanValidationContext<?> validationContext, BeanValueContext<U, Object> valueContext) {
final BeanMetaData<U> beanMetaData = valueContext.getCurrentBeanMetaData();
final Map<Class<?>, Class<?>> validatedInterfaces = new HashMap<>();
// 评估层次结构中每个类的bean约束,这对于检测潜在的默认组重新定义是必要的
for ( Class<? super U> clazz : beanMetaData.getClassHierarchy() ) {
// 获取父类的BeanMetaData
BeanMetaData<? super U> hostingBeanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
// 获取是否定义了默认组序列。如果通过组序列重新定义或组序列提供程序重新定义了默认组序列,返回true
boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.isDefaultGroupSequenceRedefined();
// 如果当前类重新定义了默认的组序列,则必须将该序列应用于所有类层次结构
if ( defaultGroupSequenceIsRedefined ) {
// 获取当前beanClass的分组序列。如果定义了DefaultGroupSequenceProvider,则执行getValidationGroups(),获得动态分组序列
Iterator<Sequence> defaultGroupSequence = hostingBeanMetaData.getDefaultValidationSequence( valueContext.getCurrentBean() );
Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getMetaConstraints();
// 遍历分组序列
while ( defaultGroupSequence.hasNext() ) {
// 过滤每个序列中添加的分组(存在嵌套@GroupSequence)
for ( GroupWithInheritance groupOfGroups : defaultGroupSequence.next() ) {
boolean validationSuccessful = true;
// 遍历每个组
for ( Group defaultSequenceMember : groupOfGroups ) {
// 执行当前组的校验
validationSuccessful = validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz,
metaConstraints, defaultSequenceMember ) && validationSuccessful;
}
validationContext.markCurrentBeanAsProcessed( valueContext );
if ( !validationSuccessful ) {
break;
}
}
}
}
// fast path in case the default group sequence hasn't been redefined
else {
Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();
validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz, metaConstraints,
Group.DEFAULT_GROUP );
validationContext.markCurrentBeanAsProcessed( valueContext );
}
// all constraints in the hierarchy has been validated, stop validation.
if ( defaultGroupSequenceIsRedefined ) {
break;
}
}
}
private <U> boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanValidationContext<?> validationContext, ValueContext<U, Object> valueContext, final Map<Class<?>, Class<?>> validatedInterfaces,
Class<? super U> clazz, Set<MetaConstraint<?>> metaConstraints, Group defaultSequenceMember) {
boolean validationSuccessful = true;
// 将当前组对应的类名保存到valueContext中
valueContext.setCurrentGroup( defaultSequenceMember.getDefiningClass() );
for ( MetaConstraint<?> metaConstraint : metaConstraints ) {
// 在层次结构中多次实现的接口只需验证一次。一个接口可以定义多个约束,必须检查正在验证的类。
final Class<?> declaringClass = metaConstraint.getLocation().getDeclaringClass();
if ( declaringClass.isInterface() ) {
Class<?> validatedForClass = validatedInterfaces.get( declaringClass );
if ( validatedForClass != null && !validatedForClass.equals( clazz ) ) {
continue;
}
validatedInterfaces.put( declaringClass, clazz );
}
// 执行验证
boolean tmp = validateMetaConstraint( validationContext, valueContext, valueContext.getCurrentBean(), metaConstraint );
if ( shouldFailFast( validationContext ) ) {
return false;
}
validationSuccessful = validationSuccessful && tmp;
}
return validationSuccessful;
}
/**
* 非默认组,调用validateMetaConstraints()进行校验
*/
private void validateConstraintsForNonDefaultGroup(BaseBeanValidationContext<?> validationContext, BeanValueContext<?, Object> valueContext) {
// 调用validateMetaConstraints(),逐个遍历约束元数据,执行约束中的isValid()进行校验
validateMetaConstraints( validationContext, valueContext, valueContext.getCurrentBean(), valueContext.getCurrentBeanMetaData().getMetaConstraints() );
validationContext.markCurrentBeanAsProcessed( valueContext );
}
}
在该方法中,如果有序列分组或动态序列分组,会先执行动态序列分组的DefaultGroupSequenceProvider.getValidationGroups()获取分组序列。然后遍历分组序列,执行对应分组的校验。具体的校验方法validateMetaConstraint(),不明白的可以看。
【源码】Spring validation参数校验原理解析之Controller控制器参数校验中@RequestBody参数校验实现原理_simpleconstrainttree-CSDN博客
小结
本篇的源码量比较大,细节也比较多。建议如果本篇不太理解的,可以看看该系列的上一篇或者下一篇源码讲解文章。
关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨,一起学习。