diff --git a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java index 76c295490e..54467cd3ea 100644 --- a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java +++ b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java @@ -41,8 +41,8 @@ import static org.springframework.beans.PropertyDescriptorUtils.*; /** * Decorator for a standard {@link BeanInfo} object, e.g. as created by - * {@link Introspector#getBeanInfo(Class)}, designed to discover and register non-void - * returning setter methods. For example: + * {@link Introspector#getBeanInfo(Class)}, designed to discover and register static + * and/or non-void returning setter methods. For example: *
{@code * public class Bean { * private Foo foo; @@ -102,37 +102,40 @@ class ExtendedBeanInfo implements BeanInfo { new SimpleNonIndexedPropertyDescriptor(pd)); } - for (Method method : findNonVoidWriteMethods(delegate.getMethodDescriptors())) { - handleNonVoidWriteMethod(method); + for (Method method : findCandidateWriteMethods(delegate.getMethodDescriptors())) { + handleCandidateWriteMethod(method); } } - private ListfindNonVoidWriteMethods(MethodDescriptor[] methodDescriptors) { + private List findCandidateWriteMethods(MethodDescriptor[] methodDescriptors) { List matches = new ArrayList (); for (MethodDescriptor methodDescriptor : methodDescriptors) { Method method = methodDescriptor.getMethod(); - if (isNonVoidWriteMethod(method)) { + if (isCandidateWriteMethod(method)) { matches.add(method); } } return matches; } - public static boolean isNonVoidWriteMethod(Method method) { + public static boolean isCandidateWriteMethod(Method method) { String methodName = method.getName(); Class>[] parameterTypes = method.getParameterTypes(); int nParams = parameterTypes.length; if (methodName.length() > 3 && methodName.startsWith("set") && Modifier.isPublic(method.getModifiers()) && - !void.class.isAssignableFrom(method.getReturnType()) && + ( + !void.class.isAssignableFrom(method.getReturnType()) || + Modifier.isStatic(method.getModifiers()) + ) && (nParams == 1 || (nParams == 2 && parameterTypes[0].equals(int.class)))) { return true; } return false; } - private void handleNonVoidWriteMethod(Method method) throws IntrospectionException { + private void handleCandidateWriteMethod(Method method) throws IntrospectionException { int nParams = method.getParameterTypes().length; String propertyName = propertyNameFor(method); Class> propertyType = method.getParameterTypes()[nParams-1]; diff --git a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfoFactory.java b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfoFactory.java index 7e46211922..183ffe4e2a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfoFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfoFactory.java @@ -51,7 +51,7 @@ public class ExtendedBeanInfoFactory implements Ordered, BeanInfoFactory { */ private boolean supports(Class> beanClass) { for (Method method : beanClass.getMethods()) { - if (ExtendedBeanInfo.isNonVoidWriteMethod(method)) { + if (ExtendedBeanInfo.isCandidateWriteMethod(method)) { return true; } } diff --git a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java index 7da9710417..9ea8c569e7 100644 --- a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java @@ -1550,6 +1550,24 @@ public final class BeanWrapperTests { assertEquals(TestEnum.TEST_VALUE, consumer.getEnumValue()); } + @Test + public void cornerSpr10115() { + Spr10115Bean foo = new Spr10115Bean(); + BeanWrapperImpl bwi = new BeanWrapperImpl(); + bwi.setWrappedInstance(foo); + bwi.setPropertyValue("prop1", "val1"); + assertEquals("val1", Spr10115Bean.prop1); + } + + + static class Spr10115Bean { + private static String prop1; + + public static void setProp1(String prop1) { + Spr10115Bean.prop1 = prop1; + } + } + private static class Foo { diff --git a/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java b/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java index fd53b58af7..44062a9107 100644 --- a/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java @@ -946,4 +946,28 @@ public class ExtendedBeanInfoTests { assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true)); } } + + @Test + public void shouldSupportStaticWriteMethod() throws IntrospectionException { + { + BeanInfo bi = Introspector.getBeanInfo(WithStaticWriteMethod.class); + assertThat(hasReadMethodForProperty(bi, "prop1"), is(false)); + assertThat(hasWriteMethodForProperty(bi, "prop1"), is(false)); + assertThat(hasIndexedReadMethodForProperty(bi, "prop1"), is(false)); + assertThat(hasIndexedWriteMethodForProperty(bi, "prop1"), is(false)); + } + { + BeanInfo bi = new ExtendedBeanInfo(Introspector.getBeanInfo(WithStaticWriteMethod.class)); + assertThat(hasReadMethodForProperty(bi, "prop1"), is(false)); + assertThat(hasWriteMethodForProperty(bi, "prop1"), is(true)); + assertThat(hasIndexedReadMethodForProperty(bi, "prop1"), is(false)); + assertThat(hasIndexedWriteMethodForProperty(bi, "prop1"), is(false)); + } + } + + static class WithStaticWriteMethod { + @SuppressWarnings("unused") + public static void setProp1(String prop1) { + } + } }