小架构step系列27:Hibernate提供的validator

1 概述

直接使用Spring提供的Validation机制来校验请求参数比较麻烦,还好hibernate-validator包提供了注解的方式,在参数对象的属性上加上对应的注解,即可进行校验,这样就方便多了。本文来了解一下hibernate-validator是如何把Spring的Validation机制扩展成用注解这种便利方式的。

2 原理

2.1 加载过程

  1. 先依赖hibernate-validator包:
XML 复制代码
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

<!-- 在spring-boot-dependencies里有管理配置 -->
<properties>
    <hibernate-validator.version>6.2.5.Final</hibernate-validator.version>
</properties>
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>${hibernate-validator.version}</version>
</dependency>
  1. 在hibernate-validator包里包含了文件/META-INF/services/javax.validation.spi.ValidationProvider,文件里配置了HibernateValidator类
java 复制代码
org.hibernate.validator.HibernateValidator

Spring里提供了专门加载/META-INF/services目录的方法,正是通过这种方式可以支持第三方包来扩展。

  1. 加载过程:
java 复制代码
// 在spring-boot-autoconfigure包里有ValidationAutoConfiguration类,是一个带@AutoConfiguration注解的配置类。
// 当检测到classpath下有META-INF/services/javax.validation.spi.ValidationProvider时,
// 会触发ValidationAutoConfiguration这个配置类的加载。
// 源码位置:org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(ExecutableValidator.class)
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
@Import(PrimaryDefaultValidatorPostProcessor.class)
public class ValidationAutoConfiguration {
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @ConditionalOnMissingBean(Validator.class)
    public static LocalValidatorFactoryBean defaultValidator(ApplicationContext applicationContext) {
        // 1. 创建一个LocalValidatorFactoryBean对象,把对象作为bean
        //    LocalValidatorFactoryBean实现了InitializingBean接口,bean创建完成后执行afterPropertiesSet()
        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
        MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory(applicationContext);
        factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
        return factoryBean;
    }
    // 省略其它代码
}

// 源码位置:org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
public void afterPropertiesSet() {
    Configuration<?> configuration;
    if (this.providerClass != null) {
        ProviderSpecificBootstrap bootstrap = Validation.byProvider(this.providerClass);
        if (this.validationProviderResolver != null) {
            bootstrap = bootstrap.providerResolver(this.validationProviderResolver);
        }
        configuration = bootstrap.configure();
    }
    else {
        // 2. 加载默认的GenericBootstrap,其实现类为GenericBootstrapImpl
        GenericBootstrap bootstrap = Validation.byDefaultProvider();
        if (this.validationProviderResolver != null) {
            bootstrap = bootstrap.providerResolver(this.validationProviderResolver);
        }
        // 3. 进行配置
        configuration = bootstrap.configure();
    }

    if (this.applicationContext != null) {
        try {
            Method eclMethod = configuration.getClass().getMethod("externalClassLoader", ClassLoader.class);
            ReflectionUtils.invokeMethod(eclMethod, configuration, this.applicationContext.getClassLoader());
        }
        catch (NoSuchMethodException ex) {
        }
    }

    MessageInterpolator targetInterpolator = this.messageInterpolator;
    if (targetInterpolator == null) {
        targetInterpolator = configuration.getDefaultMessageInterpolator();
    }
    configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));

    if (this.traversableResolver != null) {
        configuration.traversableResolver(this.traversableResolver);
    }

    ConstraintValidatorFactory targetConstraintValidatorFactory = this.constraintValidatorFactory;
    if (targetConstraintValidatorFactory == null && this.applicationContext != null) {
        targetConstraintValidatorFactory =
                new SpringConstraintValidatorFactory(this.applicationContext.getAutowireCapableBeanFactory());
    }
    if (targetConstraintValidatorFactory != null) {
        configuration.constraintValidatorFactory(targetConstraintValidatorFactory);
    }

    if (this.parameterNameDiscoverer != null) {
        configureParameterNameProvider(this.parameterNameDiscoverer, configuration);
    }

    List<InputStream> mappingStreams = null;
    if (this.mappingLocations != null) {
        mappingStreams = new ArrayList<>(this.mappingLocations.length);
        for (Resource location : this.mappingLocations) {
            try {
                InputStream stream = location.getInputStream();
                mappingStreams.add(stream);
                configuration.addMapping(stream);
            }
            catch (IOException ex) {
                closeMappingStreams(mappingStreams);
                throw new IllegalStateException("Cannot read mapping resource: " + location);
            }
        }
    }

    this.validationPropertyMap.forEach(configuration::addProperty);

    if (this.configurationInitializer != null) {
        this.configurationInitializer.accept(configuration);
    }
    postProcessConfiguration(configuration);

    try {
        this.validatorFactory = configuration.buildValidatorFactory();
        setTargetValidator(this.validatorFactory.getValidator());
    }
    finally {
        closeMappingStreams(mappingStreams);
    }
}

// 源码位置:javax.validation.Validation.GenericBootstrapImpl
public Configuration<?> configure() {
    // ValidationProviderResolver为DefaultValidationProviderResolver
    ValidationProviderResolver resolver = this.resolver == null ? this.getDefaultValidationProviderResolver() : this.resolver;

    List<ValidationProvider<?>> validationProviders;
    try {
        // 4. 加载所有ValidationProvider
        validationProviders = resolver.getValidationProviders();
    } catch (ValidationException e) {
        throw e;
    } catch (RuntimeException re) {
        throw new ValidationException("Unable to get available provider resolvers.", re);
    }

    if (validationProviders.isEmpty()) {
        String msg = "Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.";
        throw new NoProviderFoundException(msg);
    } else {
        try {
            Configuration<?> config = ((ValidationProvider)resolver.getValidationProviders().get(0)).createGenericConfiguration(this);
            return config;
        } catch (RuntimeException re) {
            throw new ValidationException("Unable to instantiate Configuration.", re);
        }
    }
}

// 源码位置:javax.validation.Validation.DefaultValidationProviderResolver
public List<ValidationProvider<?>> getValidationProviders() {
    // 5. 加载ValidationProvider列表
    return Validation.GetValidationProviderListAction.getValidationProviderList();
}

// 源码位置:javax.validation.Validation.GetValidationProviderListAction
public static synchronized List<ValidationProvider<?>> getValidationProviderList() {
    // 5. 执行run()方法加载,INSTANCE就是Validation.GetValidationProviderListAction的对象
    return System.getSecurityManager() != null ? (List)AccessController.doPrivileged(INSTANCE) : INSTANCE.run();
}

// 源码位置:javax.validation.Validation.GetValidationProviderListAction
public List<ValidationProvider<?>> run() {
    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    List<ValidationProvider<?>> cachedContextClassLoaderProviderList = this.getCachedValidationProviders(classloader);
    if (cachedContextClassLoaderProviderList != null) {
        return cachedContextClassLoaderProviderList;
    } else {    
        // 6. 使用ClassLoader去加载
        List<ValidationProvider<?>> validationProviderList = this.loadProviders(classloader);
        if (validationProviderList.isEmpty()) {
            classloader = DefaultValidationProviderResolver.class.getClassLoader();
            List<ValidationProvider<?>> cachedCurrentClassLoaderProviderList = this.getCachedValidationProviders(classloader);
            if (cachedCurrentClassLoaderProviderList != null) {
                return cachedCurrentClassLoaderProviderList;
            }

            validationProviderList = this.loadProviders(classloader);
        }

        // 加载到的类会缓存起来
        this.cacheValidationProviders(classloader, validationProviderList);
        return validationProviderList;
    }
}

// 源码位置:javax.validation.Validation.GetValidationProviderListAction
private List<ValidationProvider<?>> loadProviders(ClassLoader classloader) {
    // 7. ServiceLoader就是Spring提供的专门加载所有jar内META-INF/services/目录指定类型类的加载器,
    //    hibernate-validator包里有/META-INF/services/javax.validation.spi.ValidationProvider文件,
    //    该文件里配置的org.hibernate.validator.HibernateValidator类就是ValidationProvider类型的
    ServiceLoader<ValidationProvider> loader = ServiceLoader.load(ValidationProvider.class, classloader);
    Iterator<ValidationProvider> providerIterator = loader.iterator();
    List<ValidationProvider<?>> validationProviderList = new ArrayList();

    while(providerIterator.hasNext()) {
        try {
            validationProviderList.add(providerIterator.next());
        } catch (ServiceConfigurationError var6) {
        }
    }

    // 这里列表里只有一个HibernateValidator对象
    return validationProviderList;
}

// 回到GenericBootstrapImpl的configure()继续处理
// 源码位置:javax.validation.Validation.GenericBootstrapImpl
public Configuration<?> configure() {
    // ValidationProviderResolver为DefaultValidationProviderResolver
    ValidationProviderResolver resolver = this.resolver == null ? this.getDefaultValidationProviderResolver() : this.resolver;

    List<ValidationProvider<?>> validationProviders;
    try {
        // 4. 加载所有ValidationProvider
        validationProviders = resolver.getValidationProviders();
    } catch (ValidationException e) {
        throw e;
    } catch (RuntimeException re) {
        throw new ValidationException("Unable to get available provider resolvers.", re);
    }

    if (validationProviders.isEmpty()) {
        String msg = "Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.";
        throw new NoProviderFoundException(msg);
    } else {
        try {
            // 8. 取出第一个ValidationProvider进行创建配置信息
            Configuration<?> config = ((ValidationProvider)resolver.getValidationProviders().get(0)).createGenericConfiguration(this);
            return config;
        } catch (RuntimeException re) {
            throw new ValidationException("Unable to instantiate Configuration.", re);
        }
    }
}


// 源码位置:org.hibernate.validator.HibernateValidator
public Configuration<?> createGenericConfiguration(BootstrapState state) {
    // 9. 创建HibernateValidator的ConfigurationImpl配置信息
    return new ConfigurationImpl( state );
}

// 回到LocalValidatorFactoryBean的afterPropertiesSet()继续处理
// 源码位置:org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
public void afterPropertiesSet() {
    Configuration<?> configuration;
    if (this.providerClass != null) {
        ProviderSpecificBootstrap bootstrap = Validation.byProvider(this.providerClass);
        if (this.validationProviderResolver != null) {
            bootstrap = bootstrap.providerResolver(this.validationProviderResolver);
        }
        configuration = bootstrap.configure();
    }
    else {
        // 2. 加载默认的GenericBootstrap,其实现类为GenericBootstrapImpl
        GenericBootstrap bootstrap = Validation.byDefaultProvider();
        if (this.validationProviderResolver != null) {
            bootstrap = bootstrap.providerResolver(this.validationProviderResolver);
        }
        // 3. 进行配置
        configuration = bootstrap.configure();
    }

    if (this.applicationContext != null) {
        try {
            Method eclMethod = configuration.getClass().getMethod("externalClassLoader", ClassLoader.class);
            ReflectionUtils.invokeMethod(eclMethod, configuration, this.applicationContext.getClassLoader());
        }
        catch (NoSuchMethodException ex) {
        }
    }

    // 省略部分代码

    try {
        // 10. 调用HibernateValidator的ConfigurationImpl配置信息的buildValidatorFactory()方法创建个工厂类,
        this.validatorFactory = configuration.buildValidatorFactory();
        // 11. 通过工厂类对象的getValidator()去创建Validator
        setTargetValidator(this.validatorFactory.getValidator());
    }
    finally {
        closeMappingStreams(mappingStreams);
    }
}
// 源码位置:org.hibernate.validator.HibernateValidator
public ValidatorFactory buildValidatorFactory(ConfigurationState configurationState) {
    return new ValidatorFactoryImpl( configurationState );
}
// 源码位置:org.hibernate.validator.internal.engine.ValidatorFactoryImpl
public Validator getValidator() {
    // 12. 创建Validator
    return createValidator(
            constraintCreationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory(),
            constraintCreationContext,
            validatorFactoryScopedContext,
            methodValidationConfiguration
    );
}
// 源码位置:org.hibernate.validator.internal.engine.ValidatorFactoryImpl
Validator createValidator(ConstraintValidatorFactory constraintValidatorFactory,
        ConstraintCreationContext constraintCreationContext,
        ValidatorFactoryScopedContext validatorFactoryScopedContext,
        MethodValidationConfiguration methodValidationConfiguration) {
    // 省略部分代码
    
    // 13. 创建Validator(ValidatorImpl)
    //     org.hibernate.validator.internal.engine.ValidatorImpl为hibernate-validator包提供的Validator类,
    //     ValidatorImpl实现了javax.validation.Validator接口
    return new ValidatorImpl(
            constraintValidatorFactory,
            beanMetaDataManager,
            constraintCreationContext.getValueExtractorManager(),
            constraintCreationContext.getConstraintValidatorManager(),
            validationOrderGenerator,
            validatorFactoryScopedContext
    );
}

// 回到LocalValidatorFactoryBean的afterPropertiesSet()继续处理
// 源码位置:org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
public void afterPropertiesSet() {
    Configuration<?> configuration;
    if (this.providerClass != null) {
        ProviderSpecificBootstrap bootstrap = Validation.byProvider(this.providerClass);
        if (this.validationProviderResolver != null) {
            bootstrap = bootstrap.providerResolver(this.validationProviderResolver);
        }
        configuration = bootstrap.configure();
    }
    else {
        // 2. 加载默认的GenericBootstrap,其实现类为GenericBootstrapImpl
        GenericBootstrap bootstrap = Validation.byDefaultProvider();
        if (this.validationProviderResolver != null) {
            bootstrap = bootstrap.providerResolver(this.validationProviderResolver);
        }
        // 3. 进行配置
        configuration = bootstrap.configure();
    }

    if (this.applicationContext != null) {
        try {
            Method eclMethod = configuration.getClass().getMethod("externalClassLoader", ClassLoader.class);
            ReflectionUtils.invokeMethod(eclMethod, configuration, this.applicationContext.getClassLoader());
        }
        catch (NoSuchMethodException ex) {
        }
    }

    // 省略部分代码

    try {
        // 10. 调用HibernateValidator的ConfigurationImpl配置信息的buildValidatorFactory()方法创建个工厂类,
        //     然后通过工厂创建出HibernateValidator对象
        this.validatorFactory = configuration.buildValidatorFactory();
        // 11. 通过工厂类对象的getValidator()去创建Validator
        // 14. 通过setTargetValidator()设置validator,注意当前类是LocalValidatorFactoryBean,继承了SpringValidatorAdapter,
        //     SpringValidatorAdapter的setTargetValidator()就是把validator赋值给targetValidator
        setTargetValidator(this.validatorFactory.getValidator());
    }
    finally {
        closeMappingStreams(mappingStreams);
    }
}

// 源码位置:org.springframework.validation.beanvalidation.SpringValidatorAdapter
void setTargetValidator(javax.validation.Validator targetValidator) {
    // 15. 把创建的Validator(ValidatorImpl)赋值给targetValidator
    this.targetValidator = targetValidator;
}
public void validate(Object target, Errors errors) {
    // 16. 最终校验的时候,用targetValidator来校验
    if (this.targetValidator != null) {
        processConstraintViolations(this.targetValidator.validate(target), errors);
    }
}

从上面看,Spring还提供了一种通过javax.validation.spi.ValidationProvider来扩展的方式,ValidationProvider提供一个接口得以指定一个Validator的工厂类,通过这个工厂类则创建出实际的Validator,把该Validator指到SpringValidatorAdapter里的targetValidator,这样就可以跟SpringMVC里使用Validator的流程接上。

2.2 查找配置了要校验的属性

在SpringMVC使用Validator进行校验的流程上,最终使用Validator的validate()方法进行校验。hibernate-validator包提供了一套注解,通过这些注解就很容易指定一些基础的校验,比如@NotNull注解就可以校验属性值不能为null,@Max就可以校验整形数字的最大范围,在javax.validation.constraints包里还提供了各种各样的注解来帮助校验一些通用的规则。当然如果是具体业务的校验,则可以自己校验或者自定义注解来完成校验。

要实现这种便利的校验,第一步就是要找到指定了这些注解的地方,称为Constraint。

java 复制代码
// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
public final <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
    Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
    sanityCheckGroups( groups );
    Class<T> rootBeanClass = (Class<T>) object.getClass();
    
    // 1. 获取参数对象的Meta信息,包含所有方法和属性
    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 );
}

// 中间略过以下步骤,直接到AnnotationMetaDataProvider的retrieveBeanConfiguration
//    org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl#getBeanMetaData
//    org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl#createBeanMetaData
//    org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl#getBeanConfigurationForHierarchy
//    org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider#getBeanConfiguration
// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private <T> BeanConfiguration<T> retrieveBeanConfiguration(Class<T> beanClass) {
    // 2. 先获取属性的Meta信息
    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 );
    }

    return new BeanConfiguration<>(
            ConfigurationSource.ANNOTATION,
            beanClass,
            constrainedElements,
            getDefaultGroupSequence( beanClass ),
            getDefaultGroupSequenceProvider( beanClass )
    );
}

// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private Set<ConstrainedElement> getFieldMetaData(Class<?> beanClass) {
    Set<ConstrainedElement> propertyMetaData = newHashSet();

    for ( Field field : run( GetDeclaredFields.action( beanClass ) ) ) {
        if ( Modifier.isStatic( field.getModifiers() ) || field.isSynthetic() ) {
            continue;
        }

        JavaBeanField javaBeanField = javaBeanHelper.field( field );

        if ( annotationProcessingOptions.areMemberConstraintsIgnoredFor( javaBeanField ) ) {
            continue;
        }

        // 3. 遍历类里的所有DeclaredFields,获取Field的meta信息
        propertyMetaData.add( findPropertyMetaData( javaBeanField ) );
    }
    return propertyMetaData;
}

// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private ConstrainedField findPropertyMetaData(JavaBeanField javaBeanField) {
    // 4. 获取Field的Constraint信息
    Set<MetaConstraint<?>> constraints = convertToMetaConstraints(
            findConstraints( javaBeanField, ConstraintLocationKind.FIELD ),
            javaBeanField
    );

    CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( javaBeanField );
    Set<MetaConstraint<?>> typeArgumentsConstraints = findTypeAnnotationConstraints( javaBeanField );

    return new ConstrainedField(
            ConfigurationSource.ANNOTATION,
            javaBeanField,
            constraints,
            typeArgumentsConstraints,
            cascadingMetaDataBuilder
    );
}
private List<ConstraintDescriptorImpl<?>> findConstraints(JavaBeanAnnotatedConstrainable constrainable, ConstraintLocationKind kind) {
    // 5. 获取Field的Constraint信息,constrainable为Field
    return findConstraints( constrainable, constrainable, kind );
}
private List<ConstraintDescriptorImpl<?>> findConstraints(Constrainable constrainable, JavaBeanAnnotatedElement annotatedElement, ConstraintLocationKind kind) {
    List<ConstraintDescriptorImpl<?>> metaData = newArrayList();
    for ( Annotation annotation : annotatedElement.getDeclaredAnnotations() ) {
        // 6. 遍历Field的所有注解,从注解里获取Constraint信息
        metaData.addAll( findConstraintAnnotations( constrainable, annotation, kind ) );
    }

    return metaData;
}

// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
protected <A extends Annotation> List<ConstraintDescriptorImpl<?>> findConstraintAnnotations(
        Constrainable constrainable,
        A annotation,
        ConstraintLocationKind type) {
    // 7. 如果注解的包路径是以"java."、"jdk.internal"这两种开头,则不算Constraint,返回空列表
    if ( constraintCreationContext.getConstraintHelper().isJdkAnnotation( annotation.annotationType() ) ) {
        return Collections.emptyList();
    }

    List<Annotation> constraints = newArrayList();
    Class<? extends Annotation> annotationType = annotation.annotationType();
    // 8. 判断是否是Constraint注解,Helper为ConstraintHelper
    if ( constraintCreationContext.getConstraintHelper().isConstraintAnnotation( annotationType ) ) {
        constraints.add( annotation );
    }
    else if ( constraintCreationContext.getConstraintHelper().isMultiValueConstraint( annotationType ) ) {
        constraints.addAll( constraintCreationContext.getConstraintHelper().getConstraintsFromMultiValueConstraint( annotation ) );
    }

    return constraints.stream()
            .map( c -> buildConstraintDescriptor( constrainable, c, type ) )
            .collect( Collectors.toList() );
}

// 源码位置:org.hibernate.validator.internal.metadata.core.ConstraintHelper
public boolean isConstraintAnnotation(Class<? extends Annotation> annotationType) {
    // 9. 判断是否是内置的Constraint注解
    if ( isBuiltinConstraint( annotationType ) ) {
        return true;
    }

    if ( annotationType.getAnnotation( Constraint.class ) == null ) {
        return false;
    }

    return externalConstraints.computeIfAbsent( annotationType, a -> {
        assertMessageParameterExists( a );
        assertGroupsParameterExists( a );
        assertPayloadParameterExists( a );
        assertValidationAppliesToParameterSetUpCorrectly( a );
        assertNoParameterStartsWithValid( a );

        return Boolean.TRUE;
    } );
}
private boolean isBuiltinConstraint(Class<? extends Annotation> annotationType) {
    // 10. 判断是否是内置的Constraint注解Map里
    return BuiltinConstraint.isBuiltin( annotationType.getName() );
}

// 源码位置:org.hibernate.validator.internal.metadata.core.BuiltinConstraint
static boolean isBuiltin(String constraint) {
    // 11. 判断注解的名称是否在内置Constraint注解Map里
    return CONSTRAINT_MAPPING.containsKey( constraint );
}
// CONSTRAINT_MAPPING里初始化了50种Constraint,常见的如NotNull、NotEmpty、Min、Max等
enum BuiltinConstraint {
    // Specification constraints
    JAVAX_VALIDATION_CONSTRAINTS_ASSERT_FALSE("javax.validation.constraints.AssertFalse"),
    JAVAX_VALIDATION_CONSTRAINTS_ASSERT_TRUE("javax.validation.constraints.AssertTrue"),
    JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MAX("javax.validation.constraints.DecimalMax"),
    JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MIN("javax.validation.constraints.DecimalMin"),
    JAVAX_VALIDATION_CONSTRAINTS_DIGITS("javax.validation.constraints.Digits"),
    JAVAX_VALIDATION_CONSTRAINTS_EMAIL("javax.validation.constraints.Email"),
    JAVAX_VALIDATION_CONSTRAINTS_FUTURE("javax.validation.constraints.Future"),
    JAVAX_VALIDATION_CONSTRAINTS_FUTURE_OR_PRESENT("javax.validation.constraints.FutureOrPresent"),
    JAVAX_VALIDATION_CONSTRAINTS_MIN("javax.validation.constraints.Min"),
    JAVAX_VALIDATION_CONSTRAINTS_MAX("javax.validation.constraints.Max"),
    JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE("javax.validation.constraints.Negative"),
    JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE_OR_ZERO("javax.validation.constraints.NegativeOrZero"),
    JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK("javax.validation.constraints.NotBlank"),
    JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY("javax.validation.constraints.NotEmpty"),
    JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL("javax.validation.constraints.NotNull"),
    JAVAX_VALIDATION_CONSTRAINTS_NULL("javax.validation.constraints.Null"),
    JAVAX_VALIDATION_CONSTRAINTS_PAST("javax.validation.constraints.Past"),
    JAVAX_VALIDATION_CONSTRAINTS_PAST_OR_PRESENT("javax.validation.constraints.PastOrPresent"),
    JAVAX_VALIDATION_CONSTRAINTS_PATTERN("javax.validation.constraints.Pattern"),
    JAVAX_VALIDATION_CONSTRAINTS_POSITIVE("javax.validation.constraints.Positive"),
    JAVAX_VALIDATION_CONSTRAINTS_POSITIVE_OR_ZERO("javax.validation.constraints.PositiveOrZero"),
    JAVAX_VALIDATION_CONSTRAINTS_SIZE("javax.validation.constraints.Size"),

    // Hibernate Validator specific constraints
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CODE_POINT_LENGTH("org.hibernate.validator.constraints.CodePointLength"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CURRENCY("org.hibernate.validator.constraints.Currency"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EMAIL("org.hibernate.validator.constraints.Email", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN ) ),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_ISBN("org.hibernate.validator.constraints.ISBN"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LENGTH("org.hibernate.validator.constraints.Length"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK("org.hibernate.validator.constraints.LuhnCheck"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CREDIT_CARD_NUMBER("org.hibernate.validator.constraints.CreditCardNumber", Arrays.asList( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK ) ),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK("org.hibernate.validator.constraints.Mod10Check"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK("org.hibernate.validator.constraints.Mod11Check"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK("org.hibernate.validator.constraints.ModCheck"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NORMALIZED("org.hibernate.validator.constraints.Normalized"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EAN("org.hibernate.validator.constraints.EAN", Arrays.asList( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK ) ),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK("org.hibernate.validator.constraints.NotBlank", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_EMPTY("org.hibernate.validator.constraints.NotEmpty", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL, JAVAX_VALIDATION_CONSTRAINTS_SIZE )),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PARAMETER_SCRIPT_ASSERT("org.hibernate.validator.constraints.ParameterScriptAssert"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RANGE("org.hibernate.validator.constraints.Range", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_MIN, JAVAX_VALIDATION_CONSTRAINTS_MAX )),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SCRIPT_ASSERT("org.hibernate.validator.constraints.ScriptAssert"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_URL("org.hibernate.validator.constraints.URL", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_UNIQUE_ELEMENTS("org.hibernate.validator.constraints.UniqueElements"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CNPJ("org.hibernate.validator.constraints.br.CNPJ", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CPF("org.hibernate.validator.constraints.br.CPF", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_TITULO_ELEITORAL("org.hibernate.validator.constraints.br.TituloEleitoral", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN, ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK ) ),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_NIP("org.hibernate.validator.constraints.pl.NIP"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_PESEL("org.hibernate.validator.constraints.pl.PESEL"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_REGON("org.hibernate.validator.constraints.pl.REGON"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RU_INN("org.hibernate.validator.constraints.ru.INN"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MAX("org.hibernate.validator.constraints.time.DurationMax"),
    ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MIN("org.hibernate.validator.constraints.time.DurationMin");

    private static final Map<String, Set<BuiltinConstraint>> CONSTRAINT_MAPPING;
    // 省略其它代码
}

// 回到ConstraintHelper的isConstraintAnnotation()继续处理
// 源码位置:org.hibernate.validator.internal.metadata.core.ConstraintHelper
public boolean isConstraintAnnotation(Class<? extends Annotation> annotationType) {
    // 9. 判断是否是内置的Constraint注解
    if ( isBuiltinConstraint( annotationType ) ) {
        return true;
    }

    // 12. 也可以自定义注解,并用Constraint注解标记,细节自行探索
    if ( annotationType.getAnnotation( Constraint.class ) == null ) {
        return false;
    }

    return externalConstraints.computeIfAbsent( annotationType, a -> {
        assertMessageParameterExists( a );
        assertGroupsParameterExists( a );
        assertPayloadParameterExists( a );
        assertValidationAppliesToParameterSetUpCorrectly( a );
        assertNoParameterStartsWithValid( a );

        return Boolean.TRUE;
    } );
}

// 回到AnnotationMetaDataProvider的findConstraintAnnotations()继续处理
// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
protected <A extends Annotation> List<ConstraintDescriptorImpl<?>> findConstraintAnnotations(
        Constrainable constrainable,
        A annotation,
        ConstraintLocationKind type) {
    // 7. 如果注解的包路径是以"java."、"jdk.internal"这两种开头,则不算Constraint,返回空列表
    if ( constraintCreationContext.getConstraintHelper().isJdkAnnotation( annotation.annotationType() ) ) {
        return Collections.emptyList();
    }

    List<Annotation> constraints = newArrayList();
    Class<? extends Annotation> annotationType = annotation.annotationType();
    // 8. 判断是否是Constraint注解,Helper为ConstraintHelper
    if ( constraintCreationContext.getConstraintHelper().isConstraintAnnotation( annotationType ) ) {
        constraints.add( annotation );
    }
    else if ( constraintCreationContext.getConstraintHelper().isMultiValueConstraint( annotationType ) ) {
        constraints.addAll( constraintCreationContext.getConstraintHelper().getConstraintsFromMultiValueConstraint( annotation ) );
    }

    // 13. 组装ConstraintDescriptorImpl
    return constraints.stream()
            .map( c -> buildConstraintDescriptor( constrainable, c, type ) )
            .collect( Collectors.toList() );
}


// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private <A extends Annotation> ConstraintDescriptorImpl<A> buildConstraintDescriptor(Constrainable constrainable, A annotation, ConstraintLocationKind type) {
    // 14. 创建ConstraintDescriptorImpl
    return new ConstraintDescriptorImpl<>(
            constraintCreationContext.getConstraintHelper(),
            constrainable,
            new ConstraintAnnotationDescriptor<>( annotation ),
            type
    );
}

// 回到AnnotationMetaDataProvider的findPropertyMetaData()
// 源码位置:org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider
private ConstrainedField findPropertyMetaData(JavaBeanField javaBeanField) {
    // 4. 获取Field的Constraint信息
    Set<MetaConstraint<?>> constraints = convertToMetaConstraints(
            findConstraints( javaBeanField, ConstraintLocationKind.FIELD ),
            javaBeanField
    );

    CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( javaBeanField );
    Set<MetaConstraint<?>> typeArgumentsConstraints = findTypeAnnotationConstraints( javaBeanField );

    // 15. 把找到的Constraint信息放到ConstrainedFieldField中,如果没有Constraint信息则constraints为空
    //     Contraint信息最终包装到MetaData信息中
    return new ConstrainedField(
            ConfigurationSource.ANNOTATION,
            javaBeanField,
            constraints,
            typeArgumentsConstraints,
            cascadingMetaDataBuilder
    );
}

2.3 校验属性值

找到了配置要校验的注解的属性之后,每种注解都有相应的ConstraintValidator,用于实现具体的校验逻辑。比如@Notnull对应的Validator就要实现对象值不允许为null。

java 复制代码
// 回到ValidatorImpl的validate()继续处理
// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
public final <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
    Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
    sanityCheckGroups( groups );
    Class<T> rootBeanClass = (Class<T>) object.getClass();
    
    // 1. 获取参数对象的Meta信息,包含所有方法和属性
    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()
    );

    // 16. 校验参数值
    return validateInContext( validationContext, valueContext, validationOrder );
}

// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
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();
    if ( beanMetaData.isDefaultGroupSequenceRedefined() ) {
        validationOrder.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence( valueContext.getCurrentBean() ) );
    }

    Iterator<Group> groupIterator = validationOrder.getGroupIterator();
    while ( groupIterator.hasNext() ) {
        Group group = groupIterator.next();
        valueContext.setCurrentGroup( group.getDefiningClass() );
        
        // 17. 根据Contraint校验
        validateConstraintsForCurrentGroup( validationContext, valueContext );
        if ( shouldFailFast( validationContext ) ) {
            return validationContext.getFailingConstraints();
        }
    }
    
    // 省略部分代码
    return validationContext.getFailingConstraints();
}
private void validateConstraintsForCurrentGroup(BaseBeanValidationContext<?> validationContext, BeanValueContext<?, Object> valueContext) {
    if ( !valueContext.validatingDefault() ) {
        validateConstraintsForNonDefaultGroup( validationContext, valueContext );
    }
    else {
        // 18. 在默认组下校验,Hibernate validation不是纯给Spring使用的,有Group等更复杂的概念,这里忽略
        validateConstraintsForDefaultGroup( validationContext, valueContext );
    }
}


// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
private <U> void validateConstraintsForDefaultGroup(BaseBeanValidationContext<?> validationContext, BeanValueContext<U, Object> valueContext) {
    // 19. 从Context里取出参数对象的BeanMetaData信息
    final BeanMetaData<U> beanMetaData = valueContext.getCurrentBeanMetaData();
    final Map<Class<?>, Class<?>> validatedInterfaces = new HashMap<>();

    for ( Class<? super U> clazz : beanMetaData.getClassHierarchy() ) {
        BeanMetaData<? super U> hostingBeanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
        boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.isDefaultGroupSequenceRedefined();

        if ( defaultGroupSequenceIsRedefined ) {
            // 省略部分代码
        }
        else {
            // 取出参数对象里配置的Contraint信息(列表),如加了@NotNull注解时,则Contraint为包含这个注解、加注解属性等信息
            Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();
            
            // 20. 校验
            validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz, metaConstraints, Group.DEFAULT_GROUP );
            validationContext.markCurrentBeanAsProcessed( valueContext );
        }

        if ( defaultGroupSequenceIsRedefined ) {
            break;
        }
    }
}

// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
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.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 );
        }

        // 21. 校验
        boolean tmp = validateMetaConstraint( validationContext, valueContext, valueContext.getCurrentBean(), metaConstraint );
        if ( shouldFailFast( validationContext ) ) {
            return false;
        }

        validationSuccessful = validationSuccessful && tmp;
    }
    return validationSuccessful;
}

// 源码位置:org.hibernate.validator.internal.engine.ValidatorImpl
private boolean validateMetaConstraint(BaseBeanValidationContext<?> validationContext, ValueContext<?, Object> valueContext, Object parent, MetaConstraint<?> metaConstraint) {
    BeanValueContext.ValueState<Object> originalValueState = valueContext.getCurrentValueState();
    valueContext.appendNode( metaConstraint.getLocation() );
    boolean success = true;

    if ( isValidationRequired( validationContext, valueContext, metaConstraint ) ) {

        if ( parent != null ) {
            valueContext.setCurrentValidatedValue( valueContext.getValue( parent, metaConstraint.getLocation() ) );
        }
        
        // 22. 执行metaConstraint(MetaConstraint)的validateConstraint()方法进行校验
        success = metaConstraint.validateConstraint( validationContext, valueContext );

        validationContext.markConstraintProcessed( valueContext.getCurrentBean(), valueContext.getPropertyPath(), metaConstraint );
    }

    valueContext.resetValueState( originalValueState );

    return success;
}

// 源码位置:org.hibernate.validator.internal.metadata.core.MetaConstraint
public boolean validateConstraint(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext) {
    boolean success = true;
    if ( valueExtractionPath != null ) {
        Object valueToValidate = valueContext.getCurrentValidatedValue();
        if ( valueToValidate != null ) {
            TypeParameterValueReceiver receiver = new TypeParameterValueReceiver( validationContext, valueContext, valueExtractionPath );
            ValueExtractorHelper.extractValues( valueExtractionPath.getValueExtractorDescriptor(), valueToValidate, receiver );
            success = receiver.isSuccess();
        }
    }
    else {
        // 23. 做普通的校验
        success = doValidateConstraint( validationContext, valueContext );
    }
    return success;
}
private boolean doValidateConstraint(ValidationContext<?> executionContext, ValueContext<?, ?> valueContext) {
    valueContext.setConstraintLocationKind( getConstraintLocationKind() );
    // 24. 委托给constraintTree(org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree)进行校验
    boolean validationResult = constraintTree.validateConstraints( executionContext, valueContext );

    return validationResult;
}

// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree
public final boolean validateConstraints(ValidationContext<?> validationContext, ValueContext<?, ?> valueContext) {
    List<ConstraintValidatorContextImpl> violatedConstraintValidatorContexts = new ArrayList<>( 5 );
    
    // 25. 进行校验,SimpleConstraintTree继承于ConstraintTree,这里调的是SimpleConstraintTree的validateConstraints()
    validateConstraints( validationContext, valueContext, violatedConstraintValidatorContexts );
    if ( !violatedConstraintValidatorContexts.isEmpty() ) {
        for ( ConstraintValidatorContextImpl constraintValidatorContext : violatedConstraintValidatorContexts ) {
            for ( ConstraintViolationCreationContext constraintViolationCreationContext : constraintValidatorContext.getConstraintViolationCreationContexts() ) {
                validationContext.addConstraintFailure(
                        valueContext, constraintViolationCreationContext, constraintValidatorContext.getConstraintDescriptor()
                );
            }
        }
        return false;
    }
    return true;
}

// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree
protected void validateConstraints(ValidationContext<?> validationContext, ValueContext<?, ?> valueContext,
        Collection<ConstraintValidatorContextImpl> violatedConstraintValidatorContexts) {
    // 省略部分代码
    
    // 26. 获取Contraint对应的Validator,getInitializedConstraintValidator()获取的Validator会在先初始化
    ConstraintValidator<B, ?> validator = getInitializedConstraintValidator( validationContext, valueContext );

    ConstraintValidatorContextImpl constraintValidatorContext = validationContext.createConstraintValidatorContextFor(
            descriptor, valueContext.getPropertyPath()
    );

    if ( validateSingleConstraint( valueContext, constraintValidatorContext, validator ).isPresent() ) {
        violatedConstraintValidatorContexts.add( constraintValidatorContext );
    }
}

// 27. 提前初始化好Validator
// 源码位置:org.hibernate.validator.internal.metadata.core.ConstraintHelper
private ConstraintHelper(Set<BuiltinConstraint> enabledBuiltinConstraints) {
    // 省略部分代码
    if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK ) ) {
        putBuiltinConstraint( tmpConstraints, NotBlank.class, NotBlankValidator.class );
    }

    if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY ) ) {
        List<Class<? extends ConstraintValidator<NotEmpty, ?>>> notEmptyValidators = new ArrayList<>( 11 );
        notEmptyValidators.add( NotEmptyValidatorForCharSequence.class );
        notEmptyValidators.add( NotEmptyValidatorForCollection.class );
        notEmptyValidators.add( NotEmptyValidatorForArray.class );
        notEmptyValidators.add( NotEmptyValidatorForMap.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfBoolean.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfByte.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfChar.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfDouble.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfFloat.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfInt.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfLong.class );
        notEmptyValidators.add( NotEmptyValidatorForArraysOfShort.class );
        putBuiltinConstraints( tmpConstraints, NotEmpty.class, notEmptyValidators );
    }

    if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ) {
        putBuiltinConstraint( tmpConstraints, NotNull.class, NotNullValidator.class );
    }
    if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NULL ) ) {
        putBuiltinConstraint( tmpConstraints, Null.class, NullValidator.class );
    }
    // 省略部分代码
}
private static <A extends Annotation> void putBuiltinConstraints(Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>> validators,
        Class<A> constraintType, List<Class<? extends ConstraintValidator<A, ?>>> validatorTypes) {
    List<ConstraintValidatorDescriptor<?>> descriptors = new ArrayList<>( validatorTypes.size() );

    for ( Class<? extends ConstraintValidator<A, ?>> validatorType : validatorTypes ) {
        descriptors.add( ConstraintValidatorDescriptor.forBuiltinClass( validatorType, constraintType ) );
    }

    // 以注解作为Key,Validator列表作为Value
    validators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) );
}
private static <A extends Annotation> void putBuiltinConstraint(Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>> validators,
        Class<A> constraintType, Class<? extends ConstraintValidator<A, ?>> validatorType) {
    validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forBuiltinClass( validatorType, constraintType ) ) );
}

// 回到SimpleConstraintTree的validateConstraints()继续处理
// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree
protected void validateConstraints(ValidationContext<?> validationContext, ValueContext<?, ?> valueContext,
        Collection<ConstraintValidatorContextImpl> violatedConstraintValidatorContexts) {
    // 省略部分代码
    
    // 26. 获取Contraint对应的Validator,getInitializedConstraintValidator()获取的Validator会在先初始化
    ConstraintValidator<B, ?> validator = getInitializedConstraintValidator( validationContext, valueContext );

    ConstraintValidatorContextImpl constraintValidatorContext = validationContext.createConstraintValidatorContextFor(
            descriptor, valueContext.getPropertyPath()
    );

    // 28. 用获取到的Validator进行校验
    if ( validateSingleConstraint( valueContext, constraintValidatorContext, validator ).isPresent() ) {
        violatedConstraintValidatorContexts.add( constraintValidatorContext );
    }
}

// 源码位置:org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree
protected final <V> Optional<ConstraintValidatorContextImpl> validateSingleConstraint(
        ValueContext<?, ?> valueContext,
        ConstraintValidatorContextImpl constraintValidatorContext,
        ConstraintValidator<A, V> validator) {
    boolean isValid;
    try {
        // 29. 取出参数对象的属性值
        V validatedValue = (V) valueContext.getCurrentValidatedValue();
        // 30. 使用Validator的isValid()方法进行校验
        isValid = validator.isValid( validatedValue, constraintValidatorContext );
    }
    catch (RuntimeException e) {
        if ( e instanceof ConstraintDeclarationException ) {
            throw e;
        }
        throw LOG.getExceptionDuringIsValidCallException( e );
    }
    if ( !isValid ) {
        //We do not add these violations yet, since we don't know how they are
        //going to influence the final boolean evaluation
        return Optional.of( constraintValidatorContext );
    }
    return Optional.empty();
}

// 源码位置:javax.validation.ConstraintValidator
public interface ConstraintValidator<A extends Annotation, T> {
    default void initialize(A constraintAnnotation) {
    }
    boolean isValid(T value, ConstraintValidatorContext context);
}

2.4 常见的几个ConstraintValidator

ConstraintValidator也是一个可扩展的设计,通过几个常见的ConstraintValidator来了解一下ConstraintValidator是如何实现的。

java 复制代码
// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.NullValidator
public class NullValidator implements ConstraintValidator<Null, Object> {
    @Override
    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
        // 对象值为null则通过校验
        return object == null;
    }
}


// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator
public class NotNullValidator implements ConstraintValidator<NotNull, Object> {
    @Override
    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
        // 对象值不为null则通过校验
        return object != null;
    }
}


// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.NotBlankValidator
public class NotBlankValidator implements ConstraintValidator<NotBlank, CharSequence> {
    @Override
    public boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {
        // 对象值不为null且长度大于0才通过校验
        if ( charSequence == null ) {
            return false;
        }

        return charSequence.toString().trim().length() > 0;
    }
}



// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForInteger
public class MaxValidatorForInteger extends AbstractMaxValidator<Integer> {
    // 子类没有isValid方法,由父类AbstractMaxValidator提供isValid()
    @Override
    protected int compare(Integer number) {
        return NumberComparatorHelper.compare( number.longValue(), maxValue );
    }
}
// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.AbstractMaxValidator
public abstract class AbstractMaxValidator<T> implements ConstraintValidator<Max, T> {
    protected long maxValue;
    @Override
    public void initialize(Max maxValue) {
        this.maxValue = maxValue.value();
    }

    @Override
    public boolean isValid(T value, ConstraintValidatorContext constraintValidatorContext) {
        if ( value == null ) {
            return true;
        }
        // 数字比较的时候要小于等于才校验通过
        return compare( value ) <= 0;
    }
    protected abstract int compare(T number);
}
// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.NumberComparatorHelper
public static int compare(Long number, long value) {
    return number.compareTo( value );
}


// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForInteger
public class MinValidatorForInteger extends AbstractMinValidator<Integer> {
    // 子类没有isValid方法,由父类AbstractMaxValidator提供isValid()
    @Override
    protected int compare(Integer number) {
        return NumberComparatorHelper.compare( number.longValue(), minValue );
    }
}
// 源码位置:org.hibernate.validator.internal.constraintvalidators.bv.number.bound.AbstractMinValidator
public abstract class AbstractMinValidator<T> implements ConstraintValidator<Min, T> {
    protected long minValue;
    @Override
    public void initialize(Min maxValue) {
        this.minValue = maxValue.value();
    }
    @Override
    public boolean isValid(T value, ConstraintValidatorContext constraintValidatorContext) {
        if ( value == null ) {
            return true;
        }
        return compare( value ) >= 0;
    }
    protected abstract int compare(T number);
}

3 架构一小步

引入hibernate-validator包,使用@NotNull等注解来简化一些通用的校验。

相关推荐
追风少年浪子彦3 分钟前
mybatis-plus实体类主键生成策略
java·数据库·spring·mybatis·mybatis-plus
shinelord明4 分钟前
【计算机网络架构】网状型架构简介
大数据·分布式·计算机网络·架构·计算机科学与技术
tangzzzfan21 分钟前
深入 Moya:从架构设计到现代 iOS App 网络层最佳实践
架构
创码小奇客26 分钟前
Talos 使用全攻略:从基础到高阶,常见问题一网打尽
java·后端·架构
jackzhuoa1 小时前
java小白闯关记第一天(两个数相加)
java·算法·蓝桥杯·期末
Rover.x1 小时前
内存泄漏问题排查
java·linux·服务器·缓存
midsummer_woo1 小时前
基于spring boot的纺织品企业财务管理系统(源码+论文)
java·spring boot·后端
zc-code1 小时前
Spring Boot + @RefreshScope:动态刷新配置的终极指南
java·spring boot·后端
何中应2 小时前
EasyExcel使用(二:写出)
java·后端·maven·excel
minji...2 小时前
数据结构 堆(4)---TOP-K问题
java·数据结构·算法