Skip to content

Commit 6711515

Browse files
committed
Exclude FactoryBean implementation methods on CGLIB proxies as well
Issue: SPR-17374 (cherry picked from commit dc1e3b4)
1 parent 47ca7b3 commit 6711515

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,23 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
171171

172172
private boolean isFactoryBeanMetadataMethod(Method method) {
173173
Class<?> clazz = method.getDeclaringClass();
174-
return ((clazz == FactoryBean.class || clazz == SmartFactoryBean.class) &&
175-
!method.getName().equals("getObject"));
174+
175+
// Call from interface-based proxy handle, allowing for an efficient check?
176+
if (clazz.isInterface()) {
177+
return ((clazz == FactoryBean.class || clazz == SmartFactoryBean.class) &&
178+
!method.getName().equals("getObject"));
179+
}
180+
181+
// Call from CGLIB proxy handle, potentially implementing a FactoryBean method?
182+
Class<?> factoryBeanType = null;
183+
if (SmartFactoryBean.class.isAssignableFrom(clazz)) {
184+
factoryBeanType = SmartFactoryBean.class;
185+
}
186+
else if (FactoryBean.class.isAssignableFrom(clazz)) {
187+
factoryBeanType = FactoryBean.class;
188+
}
189+
return (factoryBeanType != null && !method.getName().equals("getObject") &&
190+
ClassUtils.hasMethod(factoryBeanType, method.getName(), method.getParameterTypes()));
176191
}
177192

178193
/**

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,16 @@ private void doTestProxyValidation(MyValidInterface proxy) {
123123
@Test
124124
public void testLazyValidatorForMethodValidation() {
125125
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
126-
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class, MyValidFactoryBean.class);
126+
LazyMethodValidationConfig.class, CustomValidatorBean.class,
127+
MyValidBean.class, MyValidFactoryBean.class);
128+
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
129+
}
130+
131+
@Test
132+
public void testLazyValidatorForMethodValidationWithProxyTargetClass() {
133+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
134+
LazyMethodValidationConfigWithProxyTargetClass.class, CustomValidatorBean.class,
135+
MyValidBean.class, MyValidFactoryBean.class);
127136
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
128137
}
129138

@@ -223,4 +232,17 @@ public static MethodValidationPostProcessor methodValidationPostProcessor(@Lazy
223232
}
224233
}
225234

235+
236+
@Configuration
237+
public static class LazyMethodValidationConfigWithProxyTargetClass {
238+
239+
@Bean
240+
public static MethodValidationPostProcessor methodValidationPostProcessor(@Lazy Validator validator) {
241+
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
242+
postProcessor.setValidator(validator);
243+
postProcessor.setProxyTargetClass(true);
244+
return postProcessor;
245+
}
246+
}
247+
226248
}

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,16 @@ private void doTestProxyValidation(MyValidInterface proxy) {
127127
@Test
128128
public void testLazyValidatorForMethodValidation() {
129129
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
130-
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class, MyValidFactoryBean.class);
130+
LazyMethodValidationConfig.class, CustomValidatorBean.class,
131+
MyValidBean.class, MyValidFactoryBean.class);
132+
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
133+
}
134+
135+
@Test
136+
public void testLazyValidatorForMethodValidationWithProxyTargetClass() {
137+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
138+
LazyMethodValidationConfigWithProxyTargetClass.class, CustomValidatorBean.class,
139+
MyValidBean.class, MyValidFactoryBean.class);
131140
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
132141
}
133142

@@ -227,4 +236,17 @@ public static MethodValidationPostProcessor methodValidationPostProcessor(@Lazy
227236
}
228237
}
229238

239+
240+
@Configuration
241+
public static class LazyMethodValidationConfigWithProxyTargetClass {
242+
243+
@Bean
244+
public static MethodValidationPostProcessor methodValidationPostProcessor(@Lazy Validator validator) {
245+
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
246+
postProcessor.setValidator(validator);
247+
postProcessor.setProxyTargetClass(true);
248+
return postProcessor;
249+
}
250+
}
251+
230252
}

0 commit comments

Comments
 (0)