diff --git a/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java b/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java index a290a191685..096bae5a617 100644 --- a/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java +++ b/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java @@ -69,8 +69,11 @@ class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor { // Fallback: Original JavaBeans introspection might not have found matching setter // method due to lack of bridge method resolution, in case of the getter using a // covariant return type whereas the setter is defined for the concrete property type. - writeMethodToUse = ClassUtils.getMethodIfAvailable(this.beanClass, - "set" + StringUtils.capitalize(getName()), readMethodToUse.getReturnType()); + Method candidate = ClassUtils.getMethodIfAvailable( + this.beanClass, "set" + StringUtils.capitalize(getName()), (Class>[]) null); + if (candidate != null && candidate.getParameterTypes().length == 1) { + writeMethodToUse = candidate; + } } this.readMethod = readMethodToUse; this.writeMethod = writeMethodToUse; diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index b50b875872c..0035e1ad866 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -17,15 +17,12 @@ package org.springframework.util; import java.beans.Introspector; - import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; - import java.security.AccessControlException; - import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -546,7 +543,7 @@ public abstract class ClassUtils { /** * Determine whether the given class has a public constructor with the given signature. *
Essentially translates {@code NoSuchMethodException} to "false". - * @param clazz the clazz to analyze + * @param clazz the clazz to analyze * @param paramTypes the parameter types of the method * @return whether the class has a corresponding constructor * @see Class#getMethod @@ -559,7 +556,7 @@ public abstract class ClassUtils { * Determine whether the given class has a public constructor with the given signature, * and return it if available (else return {@code null}). *
Essentially translates {@code NoSuchMethodException} to {@code null}. - * @param clazz the clazz to analyze + * @param clazz the clazz to analyze * @param paramTypes the parameter types of the method * @return the constructor, or {@code null} if not found * @see Class#getConstructor @@ -575,9 +572,9 @@ public abstract class ClassUtils { } /** - * Determine whether the given class has a method with the given signature. + * Determine whether the given class has a public method with the given signature. *
Essentially translates {@code NoSuchMethodException} to "false". - * @param clazz the clazz to analyze + * @param clazz the clazz to analyze * @param methodName the name of the method * @param paramTypes the parameter types of the method * @return whether the class has a corresponding method @@ -588,12 +585,15 @@ public abstract class ClassUtils { } /** - * Determine whether the given class has a method with the given signature, + * Determine whether the given class has a public method with the given signature, * and return it if available (else throws an {@code IllegalStateException}). + *
In case of any signature specified, only returns the method if there is a + * unique candidate, i.e. a single public method with the specified name. *
Essentially translates {@code NoSuchMethodException} to {@code IllegalStateException}.
- * @param clazz the clazz to analyze
+ * @param clazz the clazz to analyze
* @param methodName the name of the method
* @param paramTypes the parameter types of the method
+ * (may be {@code null} to indicate any signature)
* @return the method (never {@code null})
* @throws IllegalStateException if the method has not been found
* @see Class#getMethod
@@ -601,31 +601,69 @@ public abstract class ClassUtils {
public static Method getMethod(Class> clazz, String methodName, Class>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(methodName, "Method name must not be null");
- try {
- return clazz.getMethod(methodName, paramTypes);
+ if (paramTypes != null) {
+ try {
+ return clazz.getMethod(methodName, paramTypes);
+ }
+ catch (NoSuchMethodException ex) {
+ throw new IllegalStateException("Expected method not found: " + ex);
+ }
}
- catch (NoSuchMethodException ex) {
- throw new IllegalStateException("Expected method not found: " + ex);
+ else {
+ Set In case of any signature specified, only returns the method if there is a
+ * unique candidate, i.e. a single public method with the specified name.
* Essentially translates {@code NoSuchMethodException} to {@code null}.
- * @param clazz the clazz to analyze
+ * @param clazz the clazz to analyze
* @param methodName the name of the method
* @param paramTypes the parameter types of the method
+ * (may be {@code null} to indicate any signature)
* @return the method, or {@code null} if not found
* @see Class#getMethod
*/
public static Method getMethodIfAvailable(Class> clazz, String methodName, Class>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(methodName, "Method name must not be null");
- try {
- return clazz.getMethod(methodName, paramTypes);
+ if (paramTypes != null) {
+ try {
+ return clazz.getMethod(methodName, paramTypes);
+ }
+ catch (NoSuchMethodException ex) {
+ return null;
+ }
}
- catch (NoSuchMethodException ex) {
+ else {
+ Set