Spring BeanPostProcessor : MethodValidationPostProcessor

概述

MethodValidationPostProcessor处理bean中的JSR-303方法验证注解。比如某个bean方法使用了JSR-303注解如下 :

public @NotNull Object myValidMethod(@NotNull String arg1, @Max(10) int arg2)

当该bean的类上再使用了Spring的注解@Validated时,上面的这些方法就会是MethodValidationPostProcessor的关注点。

MethodValidationPostProcessor对这些验证方法的处理流程简单总结是这样的 :

  1. MethodValidationPostProcessor实现了接口InitializingBean,该bean自身的初始化逻辑会创建一个DefaultPointcutAdvisor用于向符合条件的对象添加进行方法验证的AOP advise
  2. MethodValidationPostProcessor实现了接口BeanPostProcessor定义的方法postProcessAfterInitialization,该方法会检查每个bean的创建(在该bean初始化之后),如果检测到该bean符合条件,会向其增加MethodValidationPostProcessor自身初始化时所创建的DefaultPointcutAdvisor中的AOP advise
  3. 上面例子中提到的bean方法myValidMethod被调用时,上面所提到的用于方法验证的AOP advise就会执行方法验证逻辑。

关于MethodValidationPostProcessor的使用,可以参考Spring Boot的自动配置ValidationAutoConfiguration

源代码解析

源代码版本 : Spring Context 5.1.5.RELEASE

package org.springframework.validation.beanvalidation;
// 省略 import 行

@SuppressWarnings("serial")
public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor
		implements InitializingBean {

	// 缺省支持的表示类需要进行验证的注解:Spring 的注解 @Validated
	private Class<? extends Annotation> validatedAnnotationType = Validated.class;

	// 所要使用的验证器
	@Nullable
	private Validator validator;


	/**
	 * Set the 'validated' annotation type.
	 * The default validated annotation type is the Validated annotation.
	 * <p>This setter property exists so that developers can provide their own
	 * (non-Spring-specific) annotation type to indicate that a class is supposed
	 * to be validated in the sense of applying method validation.
	 * 设置要支持的表示类需要进行验证的注解,缺省支持Spring提供的@Validated,
	 * 开发人员可以通过该方法提供自己要支持的注解类型而不一定要是Spring相关的注解
	 * @param validatedAnnotationType the desired annotation type
	 */
	public void setValidatedAnnotationType(Class<? extends Annotation> validatedAnnotationType) {
		Assert.notNull(validatedAnnotationType, "'validatedAnnotationType' must not be null");
		this.validatedAnnotationType = validatedAnnotationType;
	}

	/**
	 * Set the JSR-303 Validator to delegate to for validating methods.
	 * Default is the default ValidatorFactory's default Validator.
	 * 设置JSR-303验证器,最终的方法验证任务代理给该JSR-303验证器完成
	 */
	public void setValidator(Validator validator) {
		// Unwrap to the native Validator with forExecutables support
		if (validator instanceof LocalValidatorFactoryBean) {
			this.validator = ((LocalValidatorFactoryBean) validator).getValidator();
		}
		else if (validator instanceof SpringValidatorAdapter) {
			this.validator = validator.unwrap(Validator.class);
		}
		else {
			this.validator = validator;
		}
	}

	/**
	 * Set the JSR-303 ValidatorFactory to delegate to for validating methods,
	 * using its default Validator.
	 * Default is the default ValidatorFactory's default Validator.
	 * 设置JSR-303验证器工厂,最终的方法验证任务代理给由该JSR-303验证器工厂生成的
	 * 验证器完成。如果使用了该方法,所使用的验证器是工厂的缺省验证器。
	 * 该方法和setValidator()二者用一个即可
	 * @see javax.validation.ValidatorFactory#getValidator()
	 */
	public void setValidatorFactory(ValidatorFactory validatorFactory) {
		this.validator = validatorFactory.getValidator();
	}


	// InitializingBean 接口定义的方法,在该 BeanPostProcessor bean实例创建过程中
	// 初始化阶段执行,构造一个 DefaultPointcutAdvisor (pointcut + advise) 记录到 this.advisor
	// 用于对符合条件的方法进行验证
	@Override
	public void afterPropertiesSet() {
		Pointcut pointcut = new AnnotationMatchingPointcut(this.validatedAnnotationType, true);
		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());
	}

}

从上面的代码可以看出,MethodValidationPostProcessor继承自AbstractBeanFactoryAwareAdvisingPostProcessor,进而继承自AbstractAdvisingBeanPostProcessor。而BeanPostProcessor定义的方法实现逻辑就在该类中,它会在每个bean创建过程中初始化之后,检查该bean是否符合条件,符合条件的话,把上面所创建的方法验证advisor绑定到该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...
				// 如果当前 bean 实现了接口 Advised,
				// 并且当前 bean 没有被冻结 ,
				// 并且当前bean 符合该 MethodValidationPostProcessor 的处理条件,
				// 则将 this.advisor 添加到当前 bean,这样的它的方法被调用时,
				// this.advisor 中的方法验证逻辑就会被应用
				if (this.beforeExistingAdvisors) {
					advised.addAdvisor(0, this.advisor);
				}
				else {
					advised.addAdvisor(this.advisor);
				}
				return bean;
			}
		}

		// bean 没有实现 Advised 接口, 但是也符合 MethodValidationPostProcessor 
		// 处理条件的情况,跟上面 bean 实现了 Advised 接口的处理流程类似,只是这里
		// 是把 this.advisor 添加到当前 bean 的代理工厂类上然后生成并返回该 bean
		// 相应的代理对象,而不再是原来的 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;
	}

参考文章

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值