mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-22 22:19:03 +00:00
Ignore static get/is accessor methods in PropertyDescriptorUtils
Prior to this commit, PropertyDescriptorUtils.determineBasicProperties() incorrectly recognized static `get` and `is` accessor methods as JavaBean read methods, in contrast to the standard java.beans.Introspector, which has always excluded static methods from property discovery. This regression was introduced in Spring Framework 6.0 when determineBasicProperties() replaced the delegation to java.beans.Introspector for the fast property-discovery path used by SimpleBeanInfoFactory. As a result, an unrelated static method such as a singleton accessor could be exposed as a bean property, and reflective access to such a property (for example, via BeanWrapperImpl) could lead to a StackOverflowError if the property's value recursively exposed the same static accessor. To address that, this commit adds Modifier.isStatic(...) checks to the `get` and `is` branches in determineBasicProperties(), mirroring the equivalent check already present in CachedIntrospectionResults.isPlainAccessor(). Static `set` methods continue to be supported as write methods, consistent with the existing behavior in ExtendedBeanInfo. See gh-37068 Closes gh-37081 Signed-off-by: Arnab Nandy <arnab_nandy7@yahoo.com>
This commit is contained in:
@@ -19,6 +19,7 @@ package org.springframework.beans;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
@@ -71,11 +72,13 @@ abstract class PropertyDescriptorUtils {
|
||||
setter = true;
|
||||
nameIndex = 3;
|
||||
}
|
||||
else if (methodName.startsWith("get") && method.getParameterCount() == 0 && method.getReturnType() != void.class) {
|
||||
else if (methodName.startsWith("get") && method.getParameterCount() == 0 &&
|
||||
method.getReturnType() != void.class && !Modifier.isStatic(method.getModifiers())) {
|
||||
setter = false;
|
||||
nameIndex = 3;
|
||||
}
|
||||
else if (methodName.startsWith("is") && method.getParameterCount() == 0 && method.getReturnType() == boolean.class) {
|
||||
else if (methodName.startsWith("is") && method.getParameterCount() == 0 &&
|
||||
method.getReturnType() == boolean.class && !Modifier.isStatic(method.getModifiers())) {
|
||||
setter = false;
|
||||
nameIndex = 2;
|
||||
}
|
||||
|
||||
+18
@@ -69,6 +69,13 @@ class PropertyDescriptorUtilsPropertyResolutionTests {
|
||||
assertReadAndWriteMethodsForClassAndId(pdMap, Number.class, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void classWithStaticGetters() {
|
||||
var pdMap = resolver.resolve(ClassWithStaticGetters.class);
|
||||
|
||||
assertThat(pdMap).containsOnlyKeys("class");
|
||||
}
|
||||
|
||||
@Test
|
||||
void classWithOnlySetter() {
|
||||
var pdMap = resolver.resolve(ClassWithOnlySetter.class);
|
||||
@@ -134,6 +141,17 @@ class PropertyDescriptorUtilsPropertyResolutionTests {
|
||||
}
|
||||
}
|
||||
|
||||
static class ClassWithStaticGetters {
|
||||
|
||||
public static Long getId() {
|
||||
return 42L;
|
||||
}
|
||||
|
||||
public static boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class ClassWithOnlySetter {
|
||||
|
||||
public void setId(Long id) {
|
||||
|
||||
Reference in New Issue
Block a user