validation 是javax中定義的一套驗證接口, 目前我們大家熟悉的實現是hibernate的validation 實現 ;
問題1 , 在springboot中 validation是如何引入的?
問題2, spring中validation的驗證如何實現?
// 自動配置驗證器bean到上下文中
@Configuration
@ConditionalOnClass(ExecutableValidator.class)
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
@Import(PrimaryDefaultValidatorPostProcessor.class)
public class ValidationAutoConfiguration {
// 驗證器bean的初始化,主要是通過ServiceLoader加載 jar包中的實現類 classpath:META-INF/services/javax.validation.spi.ValidationProvider,
//例如hibernate的validation實現,
//可以通過messageInterpolatorFactory源碼獲取,詳細瞭解請看源碼
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@ConditionalOnMissingBean(Validator.class)
public static LocalValidatorFactoryBean defaultValidator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
return factoryBean;
}
// 方法級別的驗證後置處理器,
//是通過BeanPostProcessor#postProcessAfterInitialization
//方法實現通過對bean中類級別的annotation標籤(@Validated)的掃描,
//進行AOP方法攔截,進而實現啓用驗證的目的
@Bean
@ConditionalOnMissingBean
public static MethodValidationPostProcessor methodValidationPostProcessor(Environment environment,
@Lazy Validator validator) {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
boolean proxyTargetClass = environment.getProperty("spring.aop.proxy-target-class", Boolean.class, true);
processor.setProxyTargetClass(proxyTargetClass);
processor.setValidator(validator);
return processor;
}
}
問題2 , 我們具體來看MethodValidationPostProcessor這個bean的關鍵源碼
MethodValidationPostProcessor 實現InitializingBean接口
@Override
public void afterPropertiesSet() {
/** 創建一個Aop切點,切點的Annotation是 org.springframework.validation.annotation.Validated
*
*切點的兩個特性:
* 1》 this.classFilter = new AnnotationClassFilter(classAnnotationType, checkInherited); *@Validated標籤類匹配
* 2》 this.methodMatcher = MethodMatcher.TRUE; 全部方法匹配
**/
Pointcut pointcut = new AnnotationMatchingPointcut(this.validatedAnnotationType, true);
/**
切面實現 創建 MethodValidationInterceptor方法驗證攔截器實現
**/
this.advisor = new DefaultPointcutAdvisor(pointcut, createMethodValidationAdvice(this.validator));
}
/**
* Create AOP advice for method validation purposes, to be applied
* with a pointcut for the specified 'validated' annotation.
* @param validator the JSR-303 Validator to delegate to
* @return the interceptor to use (typically, but not necessarily,
* a {@link MethodValidationInterceptor} or subclass thereof)
* @since 4.2
*/
protected Advice createMethodValidationAdvice(@Nullable Validator validator) {
return (validator != null ? new MethodValidationInterceptor(validator) : new MethodValidationInterceptor());
}
同時其父類AbstractAdvisingBeanPostProcessor 又實現了 BeanPostProcessor接口 ,因此我們看下具體的實現方法:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
else {
advised.addAdvisor(this.advisor);
}
return bean;
}
}
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
return proxyFactory.getProxy(getProxyClassLoader());
}
// No proxy needed.
return bean;
}
該方法將會生成代理類(對容器中構建好的bean進行掃描 , 生成代理類)
好了 就寫到這裏了 , 如有紕漏,請留言指正, 希望能對你有所幫助!