【源码】Spring validation参数校验之分组序列校验@GroupSequenceProvider、@GroupSequence的实现原理

 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博客

小结

本篇的源码量比较大,细节也比较多。建议如果本篇不太理解的,可以看看该系列的上一篇或者下一篇源码讲解文章。

关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨,一起学习。

  • 28
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值