29
29
import java .beans .SimpleBeanInfo ;
30
30
import java .lang .reflect .Method ;
31
31
import 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 ;
35
36
36
37
import org .springframework .beans .BeanInfoFactory ;
37
38
import org .springframework .beans .BeanUtils ;
38
39
import org .springframework .core .KotlinDetector ;
39
40
import 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 ;
40
45
41
46
/**
42
47
* {@link BeanInfoFactory} specific to Kotlin types using Kotlin reflection to determine bean properties.
@@ -60,7 +65,8 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
60
65
}
61
66
62
67
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 );
64
70
65
71
for (KCallable <?> member : kotlinClass .getMembers ()) {
66
72
@@ -69,6 +75,16 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
69
75
Method getter = ReflectJvmMapping .getJavaGetter (property );
70
76
Method setter = property instanceof KMutableProperty <?> kmp ? ReflectJvmMapping .getJavaSetter (kmp ) : null ;
71
77
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
+
72
88
if (getter != null && (Modifier .isStatic (getter .getModifiers ()) || getter .getParameterCount () != 0 )) {
73
89
continue ;
74
90
}
@@ -80,7 +96,7 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
80
96
}
81
97
}
82
98
83
- pds . add ( new PropertyDescriptor (property .getName (), getter , setter ));
99
+ descriptors . put ( property . getName (), new PropertyDescriptor (property .getName (), getter , setter ));
84
100
}
85
101
}
86
102
@@ -93,9 +109,17 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
93
109
if (javaClass != Object .class ) {
94
110
95
111
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
+ }
97
119
}
98
120
121
+ PropertyDescriptor [] propertyDescriptors = descriptors .values ().toArray (new PropertyDescriptor [0 ]);
122
+
99
123
return new SimpleBeanInfo () {
100
124
@ Override
101
125
public BeanDescriptor getBeanDescriptor () {
@@ -104,11 +128,21 @@ public BeanDescriptor getBeanDescriptor() {
104
128
105
129
@ Override
106
130
public PropertyDescriptor [] getPropertyDescriptors () {
107
- return pds . toArray ( new PropertyDescriptor [ 0 ]) ;
131
+ return propertyDescriptors ;
108
132
}
109
133
};
110
134
}
111
135
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
+
112
146
@ Override
113
147
public int getOrder () {
114
148
return LOWEST_PRECEDENCE - 10 ; // leave some space for customizations.
0 commit comments