SpringBoot 中 Spring Validation 工作方式

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进行扫描 , 生成代理类)

好了 就写到这里了 , 如有纰漏,请留言指正, 希望能对你有所帮助!

你可能感兴趣的:(spring,boot,spring,validation,spring,boot,validation,spring,validation实现)