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