小架构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等注解来简化一些通用的校验。

相关推荐
百锦再7 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说7 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多7 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再7 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
DokiDoki之父8 小时前
Spring—注解开发
java·后端·spring
CodeCraft Studio8 小时前
【能源与流程工业案例】KBC借助TeeChart 打造工业级数据可视化平台
java·信息可视化·.net·能源·teechart·工业可视化·工业图表
摇滚侠8 小时前
Spring Boot 3零基础教程,WEB 开发 默认页签图标 Favicon 笔记29
java·spring boot·笔记
YSRM8 小时前
Leetcode+Java+图论+最小生成树&拓扑排序
java·leetcode·图论
wuyunhang1234569 小时前
Docker----快速入门
docker·容器·架构