2929import  java .beans .SimpleBeanInfo ;
3030import  java .lang .reflect .Method ;
3131import  java .lang .reflect .Modifier ;
32- import  java .util . Arrays ;
32+ import  java .lang . reflect . Type ;
3333import  java .util .Collection ;
34- import  java .util .LinkedHashSet ;
35- import  java .util .Set ;
34+ import  java .util .LinkedHashMap ;
35+ import  java .util .Map ;
3636
3737import  org .springframework .beans .BeanInfoFactory ;
3838import  org .springframework .beans .BeanUtils ;
3939import  org .springframework .core .KotlinDetector ;
4040import  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 ;
4145
4246/** 
4347 * {@link BeanInfoFactory} specific to Kotlin types using Kotlin reflection to determine bean properties. 
@@ -62,7 +66,7 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
6266
6367		KClass <?> kotlinClass  = JvmClassMappingKt .getKotlinClass (beanClass );
6468		Collection <KCallable <?>> members  = kotlinClass .getMembers ();
65- 		Set < PropertyDescriptor > pds  = new  LinkedHashSet <>(members .size ());
69+ 		Map < String ,  PropertyDescriptor > descriptors  = new  LinkedHashMap <>(members .size (),  1.f );
6670
6771		for  (KCallable <?> member  : members ) {
6872
@@ -71,6 +75,16 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
7175				Method  getter  = ReflectJvmMapping .getJavaGetter (property );
7276				Method  setter  = property  instanceof  KMutableProperty <?> kmp  ? ReflectJvmMapping .getJavaSetter (kmp ) : null ;
7377
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+ 
7488				if  (getter  != null  && (Modifier .isStatic (getter .getModifiers ()) || getter .getParameterCount () != 0 )) {
7589					continue ;
7690				}
@@ -82,7 +96,7 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
8296					}
8397				}
8498
85- 				pds . add ( new  PropertyDescriptor (property .getName (), getter , setter ));
99+ 				descriptors . put ( property . getName (),  new  PropertyDescriptor (property .getName (), getter , setter ));
86100			}
87101		}
88102
@@ -95,9 +109,17 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
95109		if  (javaClass  != Object .class ) {
96110
97111			PropertyDescriptor [] javaPropertyDescriptors  = BeanUtils .getPropertyDescriptors (javaClass );
98- 			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+ 			}
99119		}
100120
121+ 		PropertyDescriptor [] propertyDescriptors  = descriptors .values ().toArray (new  PropertyDescriptor [0 ]);
122+ 
101123		return  new  SimpleBeanInfo () {
102124			@ Override 
103125			public  BeanDescriptor  getBeanDescriptor () {
@@ -106,11 +128,21 @@ public BeanDescriptor getBeanDescriptor() {
106128
107129			@ Override 
108130			public  PropertyDescriptor [] getPropertyDescriptors () {
109- 				return  pds . toArray ( new   PropertyDescriptor [ 0 ]) ;
131+ 				return  propertyDescriptors ;
110132			}
111133		};
112134	}
113135
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+ 
114146	@ Override 
115147	public  int  getOrder () {
116148		return  LOWEST_PRECEDENCE  - 10 ; // leave some space for customizations. 
0 commit comments