2929import java .beans .SimpleBeanInfo ;
3030import java .lang .reflect .Method ;
3131import java .lang .reflect .Modifier ;
32- import java .util .Arrays ;
33- import java .util .LinkedHashSet ;
34- import java .util .Set ;
32+ import java .lang .reflect .Type ;
33+ import java .util .Collection ;
34+ import java .util .LinkedHashMap ;
35+ import java .util .Map ;
3536
3637import org .springframework .beans .BeanInfoFactory ;
3738import org .springframework .beans .BeanUtils ;
3839import org .springframework .core .KotlinDetector ;
3940import org .springframework .core .Ordered ;
41+ import org .springframework .lang .Nullable ;
42+ import org .springframework .util .ClassUtils ;
43+ import org .springframework .util .ReflectionUtils ;
44+ import org .springframework .util .StringUtils ;
4045
4146/**
4247 * {@link BeanInfoFactory} specific to Kotlin types using Kotlin reflection to determine bean properties.
@@ -60,7 +65,8 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
6065 }
6166
6267 KClass <?> kotlinClass = JvmClassMappingKt .getKotlinClass (beanClass );
63- Set <PropertyDescriptor > pds = new LinkedHashSet <>();
68+ Collection <KCallable <?>> members = kotlinClass .getMembers ();
69+ Map <String , PropertyDescriptor > descriptors = new LinkedHashMap <>(members .size (), 1.f );
6470
6571 for (KCallable <?> member : kotlinClass .getMembers ()) {
6672
@@ -69,6 +75,16 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
6975 Method getter = ReflectJvmMapping .getJavaGetter (property );
7076 Method setter = property instanceof KMutableProperty <?> kmp ? ReflectJvmMapping .getJavaSetter (kmp ) : null ;
7177
78+ if (getter == null ) {
79+ Type javaType = ReflectJvmMapping .getJavaType (property .getReturnType ());
80+ getter = ReflectionUtils .findMethod (beanClass ,
81+ javaType == Boolean .TYPE ? "is" : "get" + StringUtils .capitalize (property .getName ()));
82+ }
83+
84+ if (getter != null ) {
85+ getter = ClassUtils .getMostSpecificMethod (getter , beanClass );
86+ }
87+
7288 if (getter != null && (Modifier .isStatic (getter .getModifiers ()) || getter .getParameterCount () != 0 )) {
7389 continue ;
7490 }
@@ -80,7 +96,7 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
8096 }
8197 }
8298
83- pds . add ( new PropertyDescriptor (property .getName (), getter , setter ));
99+ descriptors . put ( property . getName (), new PropertyDescriptor (property .getName (), getter , setter ));
84100 }
85101 }
86102
@@ -93,9 +109,17 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
93109 if (javaClass != Object .class ) {
94110
95111 PropertyDescriptor [] javaPropertyDescriptors = BeanUtils .getPropertyDescriptors (javaClass );
96- pds .addAll (Arrays .asList (javaPropertyDescriptors ));
112+
113+ for (PropertyDescriptor descriptor : javaPropertyDescriptors ) {
114+
115+ descriptor = new PropertyDescriptor (descriptor .getName (), specialize (beanClass , descriptor .getReadMethod ()),
116+ specialize (beanClass , descriptor .getWriteMethod ()));
117+ descriptors .put (descriptor .getName (), descriptor );
118+ }
97119 }
98120
121+ PropertyDescriptor [] propertyDescriptors = descriptors .values ().toArray (new PropertyDescriptor [0 ]);
122+
99123 return new SimpleBeanInfo () {
100124 @ Override
101125 public BeanDescriptor getBeanDescriptor () {
@@ -104,11 +128,21 @@ public BeanDescriptor getBeanDescriptor() {
104128
105129 @ Override
106130 public PropertyDescriptor [] getPropertyDescriptors () {
107- return pds . toArray ( new PropertyDescriptor [ 0 ]) ;
131+ return propertyDescriptors ;
108132 }
109133 };
110134 }
111135
136+ @ Nullable
137+ private static Method specialize (Class <?> beanClass , @ Nullable Method method ) {
138+
139+ if (method == null ) {
140+ return method ;
141+ }
142+
143+ return ClassUtils .getMostSpecificMethod (method , beanClass );
144+ }
145+
112146 @ Override
113147 public int getOrder () {
114148 return LOWEST_PRECEDENCE - 10 ; // leave some space for customizations.
0 commit comments