AspectJ切面自定义注解实现参数分组校验——基础概念(1)
- 一、环境
- 二、validation-api源码解读
- 2-1.Default源码解读
- 2-2.valid源码解读
- 2-3.Validation源码解读
一、环境
maven
需要引入的依赖:
<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>2.0.1.Final</version>
</dependency>
二、validation-api源码解读
通常使用validation-api对参数校验会使用@valid
注解配合@NotBlank
、@NotNull
等注解使用进行参数校验。
@NotNull(message = "金额不能为空")private BigDecimal amount;/*** 币种*/@NotBlank(message="币种不能为空")private String currency;
但是,当前@valid
只支持对Default
组进行校验。也就是说,不支持对参数进行分多个组校验。
2-1.Default源码解读
Default
接口Reference如下,
javax.validation.groups.Default
public interface Default {
}
Default
源码阐述如下,
Default Bean Validation group.
Unless a list of groups is explicitly defined:
constraints belong to the Default group
validation applies to the Default group
Most structural constraints should belong to the default group.
可以看出,constraints(指@NotBlank
、NotNull
等注解)默认是归属默认组,Validation
验证的也只是默认组。
除非明确的定义了其他一些组。即Valid
注解只是针对默认组进行验证。
2-2.valid源码解读
Valid
注解Reference如下,
javax.validation.Valid
@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface Valid {
}
Valid
源码阐述如下,
Marks a property, method parameter or method return type for validation cascading.
Constraints defined on the object and its properties are be validated when the property, method parameter or method return type is validated.
This behavior is applied recursively.
可以看出,当constraints与@valid
注解做一种关联映射时,虽然constraints是定义在object
侧,但是对于使用了@valid
注解的属性、方法参数、方法返回参数,对应的object
侧定义的constraints,均会进行校验。这种行为应用是一种递归形式。
2-3.Validation源码解读
Validation
类Reference如下,
javax.validation.Validation
Validation
类的构成如下,
Validation
是支持用户自定义,来对Bean进行验证的一个类。源码提供了3种版本的思路:
1)思路一
直接构造默认的ValidatorFactory,
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
这种情况下,校验的提供者,可以通过XML配置定义;如果没有定义,会使用ValidationProviderResolver
返回的第一个ValidationProvider
作为校验的提供者。ValidationProviderResolver
可以保证运行时环境的可用性。
2)思路二
当然,也可以使用固定的ValidationProviderResolver
,即自己实现一个ValidationProviderResolver
来作为providerResolver(ValidationProviderResolver resolver)
的参数(如下:new MyResolverStrategy())。
Configuration<?> configuration = Validation.byDefaultProvider().providerResolver( new MyResolverStrategy() ).configure();ValidatorFactory factory = configuration.buildValidatorFactory();
3)思路三
对Configuration
实现一个自定义的子接口,来作为特定的校验提供者(如下:ACMEConfiguration)。
可以实现ValidationProvider
接口的自定义的子接口(如下:ACMEProvider),作为byProvider(Class<U> providerType)
的参数。
ACMEConfiguration configuration = Validation.byProvider(ACMEProvider.class).providerResolver( new MyResolverStrategy() ) // optionally set the provider resolver.configure();ValidatorFactory factory = configuration.buildValidatorFactory();
值得注意的是,上述构建的ValidatorFactory
需要被缓存,使Validator
消费者共享使用同一个ValidatorFactory
。
javax.validation.ValidatorFactory#getValidator