1 概述
直接使用Spring提供的Validation机制来校验请求参数比较麻烦,还好hibernate-validator包提供了注解的方式,在参数对象的属性上加上对应的注解,即可进行校验,这样就方便多了。本文来了解一下hibernate-validator是如何把Spring的Validation机制扩展成用注解这种便利方式的。
2 原理
2.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>
- 在hibernate-validator包里包含了文件/META-INF/services/javax.validation.spi.ValidationProvider,文件里配置了HibernateValidator类
java
org.hibernate.validator.HibernateValidator
Spring里提供了专门加载/META-INF/services目录的方法,正是通过这种方式可以支持第三方包来扩展。
- 加载过程:
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等注解来简化一些通用的校验。