/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.validation.beanvalidation; import java.lang.annotation.Annotation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import org.aopalliance.aop.Advice; import org.springframework.aop.Pointcut; import org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.util.Assert; import org.springframework.validation.annotation.Validated; /** * A convenient {@link BeanPostProcessor} implementation that delegates to a * JSR-303 provider for performing method-level validation on annotated methods. * * <p>Applicable methods have JSR-303 constraint annotations on their parameters * and/or on their return value (in the latter case specified at the method level, * typically as inline annotation), e.g.: * * <pre class="code"> * public @NotNull Object myValidMethod(@NotNull String arg1, @Max(10) int arg2) * </pre> * * <p>Target classes with such annotated methods need to be annotated with Spring's * {@link Validated} annotation at the type level, for their methods to be searched for * inline constraint annotations. Validation groups can be specified through {@code @Validated} * as well. By default, JSR-303 will validate against its default group only. * * <p>As of Spring 5.0, this functionality requires a Bean Validation 1.1 provider. * * @author Juergen Hoeller * @since 3.1 * @see MethodValidationInterceptor * @see javax.validation.executable.ExecutableValidator */ @SuppressWarnings("serial") public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor implements InitializingBean { private Class<? extends Annotation> validatedAnnotationType = Validated.class; private Validator validator; /** * Set the 'validated' annotation type. * The default validated annotation type is the {@link 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. * @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. * <p>Default is the default ValidatorFactory's default Validator. */ public void setValidator(Validator validator) { if (validator instanceof LocalValidatorFactoryBean) { this.validator = ((LocalValidatorFactoryBean) validator).getValidator(); } else { this.validator = validator; } } /** * Set the JSR-303 ValidatorFactory to delegate to for validating methods, * using its default Validator. * <p>Default is the default ValidatorFactory's default Validator. * @see javax.validation.ValidatorFactory#getValidator() */ public void setValidatorFactory(ValidatorFactory validatorFactory) { this.validator = validatorFactory.getValidator(); } @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(Validator validator) { return (validator != null ? new MethodValidationInterceptor(validator) : new MethodValidationInterceptor()); } }