Skip to content

Commit ebe3c27

Browse files
committed
MethodValidationInterceptor excludes FactoryBean metadata methods
Issue: SPR-17374 (cherry picked from commit 5f2d47a)
1 parent 6c9c8ef commit ebe3c27

File tree

3 files changed

+90
-9
lines changed

3 files changed

+90
-9
lines changed

spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,8 @@
2828
import org.aopalliance.intercept.MethodInvocation;
2929
import org.hibernate.validator.HibernateValidator;
3030

31+
import org.springframework.beans.factory.FactoryBean;
32+
import org.springframework.beans.factory.SmartFactoryBean;
3133
import org.springframework.core.BridgeMethodResolver;
3234
import org.springframework.core.annotation.AnnotationUtils;
3335
import org.springframework.util.ClassUtils;
@@ -112,6 +114,11 @@ public MethodValidationInterceptor(Validator validator) {
112114
@Override
113115
@SuppressWarnings("unchecked")
114116
public Object invoke(MethodInvocation invocation) throws Throwable {
117+
// Avoid Validator invocation on FactoryBean.getObjectType/isSingleton
118+
if (isFactoryBeanMetadataMethod(invocation.getMethod())) {
119+
return invocation.proceed();
120+
}
121+
115122
Class<?>[] groups = determineValidationGroups(invocation);
116123

117124
if (forExecutablesMethod != null) {
@@ -162,6 +169,12 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
162169
}
163170
}
164171

172+
private boolean isFactoryBeanMetadataMethod(Method method) {
173+
Class<?> clazz = method.getDeclaringClass();
174+
return ((clazz == FactoryBean.class || clazz == SmartFactoryBean.class) &&
175+
!method.getName().equals("getObject"));
176+
}
177+
165178
/**
166179
* Determine the validation groups to validate against for the given method invocation.
167180
* <p>Default are the validation groups as specified in the {@link Validated} annotation

spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
2727

2828
import org.springframework.aop.framework.ProxyFactory;
2929
import org.springframework.beans.MutablePropertyValues;
30+
import org.springframework.beans.factory.FactoryBean;
3031
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3132
import org.springframework.context.annotation.Bean;
3233
import org.springframework.context.annotation.Configuration;
@@ -122,8 +123,8 @@ private void doTestProxyValidation(MyValidInterface proxy) {
122123
@Test
123124
public void testLazyValidatorForMethodValidation() {
124125
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
125-
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class);
126-
ctx.getBean(MyValidInterface.class).myValidMethod("value", 5);
126+
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class, MyValidFactoryBean.class);
127+
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
127128
}
128129

129130

@@ -146,6 +147,40 @@ public String myGenericMethod(String value) {
146147
}
147148

148149

150+
@MyStereotype
151+
public static class MyValidFactoryBean implements FactoryBean<String>, MyValidInterface<String> {
152+
153+
@Override
154+
public String getObject() {
155+
return null;
156+
}
157+
158+
@Override
159+
public Class<?> getObjectType() {
160+
return String.class;
161+
}
162+
163+
@Override
164+
public boolean isSingleton() {
165+
return true;
166+
}
167+
168+
@Override
169+
public Object myValidMethod(String arg1, int arg2) {
170+
return (arg2 == 0 ? null : "value");
171+
}
172+
173+
@Override
174+
public void myValidAsyncMethod(String arg1, int arg2) {
175+
}
176+
177+
@Override
178+
public String myGenericMethod(String value) {
179+
return value;
180+
}
181+
}
182+
183+
149184
public interface MyValidInterface<T> {
150185

151186
@NotNull Object myValidMethod(@NotNull(groups = MyGroup.class) String arg1, @Max(10) int arg2);

spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/MethodValidationTests.java

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
2727

2828
import org.springframework.aop.framework.ProxyFactory;
2929
import org.springframework.beans.MutablePropertyValues;
30+
import org.springframework.beans.factory.FactoryBean;
3031
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3132
import org.springframework.context.annotation.Bean;
3233
import org.springframework.context.annotation.Configuration;
@@ -49,7 +50,6 @@
4950
* @author Juergen Hoeller
5051
* @since 4.1
5152
*/
52-
@SuppressWarnings("rawtypes")
5353
public class MethodValidationTests {
5454

5555
@Test
@@ -74,7 +74,6 @@ public void testMethodValidationPostProcessor() {
7474
ac.close();
7575
}
7676

77-
@SuppressWarnings("unchecked")
7877
private void doTestProxyValidation(MyValidInterface proxy) {
7978
assertNotNull(proxy.myValidMethod("value", 5));
8079
try {
@@ -128,8 +127,8 @@ private void doTestProxyValidation(MyValidInterface proxy) {
128127
@Test
129128
public void testLazyValidatorForMethodValidation() {
130129
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
131-
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class);
132-
ctx.getBean(MyValidInterface.class).myValidMethod("value", 5);
130+
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class, MyValidFactoryBean.class);
131+
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
133132
}
134133

135134

@@ -152,6 +151,40 @@ public String myGenericMethod(String value) {
152151
}
153152

154153

154+
@MyStereotype
155+
public static class MyValidFactoryBean implements FactoryBean<String>, MyValidInterface<String> {
156+
157+
@Override
158+
public String getObject() {
159+
return null;
160+
}
161+
162+
@Override
163+
public Class<?> getObjectType() {
164+
return String.class;
165+
}
166+
167+
@Override
168+
public boolean isSingleton() {
169+
return true;
170+
}
171+
172+
@Override
173+
public Object myValidMethod(String arg1, int arg2) {
174+
return (arg2 == 0 ? null : "value");
175+
}
176+
177+
@Override
178+
public void myValidAsyncMethod(String arg1, int arg2) {
179+
}
180+
181+
@Override
182+
public String myGenericMethod(String value) {
183+
return value;
184+
}
185+
}
186+
187+
155188
public interface MyValidInterface<T> {
156189

157190
@NotNull Object myValidMethod(@NotNull(groups = MyGroup.class) String arg1, @Max(10) int arg2);

0 commit comments

Comments
 (0)