diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java index bbcf92ea9e..42427f4c83 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -28,6 +28,8 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.hibernate.validator.HibernateValidator; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.SmartFactoryBean; import org.springframework.core.BridgeMethodResolver; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.ClassUtils; @@ -112,6 +114,11 @@ public class MethodValidationInterceptor implements MethodInterceptor { @Override @SuppressWarnings("unchecked") public Object invoke(MethodInvocation invocation) throws Throwable { + // Avoid Validator invocation on FactoryBean.getObjectType/isSingleton + if (isFactoryBeanMetadataMethod(invocation.getMethod())) { + return invocation.proceed(); + } + Class>[] groups = determineValidationGroups(invocation); if (forExecutablesMethod != null) { @@ -162,6 +169,12 @@ public class MethodValidationInterceptor implements MethodInterceptor { } } + private boolean isFactoryBeanMetadataMethod(Method method) { + Class> clazz = method.getDeclaringClass(); + return ((clazz == FactoryBean.class || clazz == SmartFactoryBean.class) && + !method.getName().equals("getObject")); + } + /** * Determine the validation groups to validate against for the given method invocation. *
Default are the validation groups as specified in the {@link Validated} annotation
diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
index a6af80e722..63746bbbf5 100644
--- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
+++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -27,6 +27,7 @@ import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -122,8 +123,8 @@ public class MethodValidationTests {
@Test
public void testLazyValidatorForMethodValidation() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
- LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class);
- ctx.getBean(MyValidInterface.class).myValidMethod("value", 5);
+ LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class, MyValidFactoryBean.class);
+ ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
}
@@ -146,6 +147,40 @@ public class MethodValidationTests {
}
+ @MyStereotype
+ public static class MyValidFactoryBean implements FactoryBean