From 973eb5deb67d7a44b5c1ff525fdde486da4cf273 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 14 Oct 2018 21:07:56 +0200 Subject: [PATCH] MethodValidationInterceptor excludes FactoryBean metadata methods Issue: SPR-17374 (cherry picked from commit 5f2d47a17eaba88a19e011e600f4f09f262e88bf) --- .../MethodValidationTests.java | 36 +++++++++++++++++-- .../MethodValidationInterceptor.java | 15 +++++++- .../beanvalidation/MethodValidationTests.java | 36 +++++++++++++++++-- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/spring-context-support/src/test/java/org/springframework/validation/beanvalidation2/MethodValidationTests.java b/spring-context-support/src/test/java/org/springframework/validation/beanvalidation2/MethodValidationTests.java index 0fed965eca..7caec1d8bf 100644 --- a/spring-context-support/src/test/java/org/springframework/validation/beanvalidation2/MethodValidationTests.java +++ b/spring-context-support/src/test/java/org/springframework/validation/beanvalidation2/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,35 @@ public class MethodValidationTests { } + @MyStereotype + public static class MyValidFactoryBean implements FactoryBean, MyValidInterface { + + @Override + public String getObject() { + return null; + } + + @Override + public Class getObjectType() { + return String.class; + } + + @Override + public Object myValidMethod(String arg1, int arg2) { + return (arg2 == 0 ? null : "value"); + } + + @Override + public void myValidAsyncMethod(String arg1, int arg2) { + } + + @Override + public String myGenericMethod(String value) { + return value; + } + } + + public interface MyValidInterface { @NotNull Object myValidMethod(@NotNull(groups = MyGroup.class) String arg1, @Max(10) int arg2); 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 9ccb286462..fcee372759 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 javax.validation.executable.ExecutableValidator; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +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; @@ -86,6 +88,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); // Standard Bean Validation 1.1 API @@ -119,6 +126,12 @@ public class MethodValidationInterceptor implements MethodInterceptor { return returnValue; } + 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 e7dadb3364..58df8de46d 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; @@ -119,8 +120,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)); } @@ -143,6 +144,35 @@ public class MethodValidationTests { } + @MyStereotype + public static class MyValidFactoryBean implements FactoryBean, MyValidInterface { + + @Override + public String getObject() { + return null; + } + + @Override + public Class getObjectType() { + return String.class; + } + + @Override + public Object myValidMethod(String arg1, int arg2) { + return (arg2 == 0 ? null : "value"); + } + + @Override + public void myValidAsyncMethod(String arg1, int arg2) { + } + + @Override + public String myGenericMethod(String value) { + return value; + } + } + + public interface MyValidInterface { @NotNull Object myValidMethod(@NotNull(groups = MyGroup.class) String arg1, @Max(10) int arg2);