Skip to content

Commit c2b56c0

Browse files
author
Phillip Webb
committed
Cache property TypeDescriptors
Attempt to improve performance by caching TypeDescriptors against bean PropertyDescriptors in CachedIntrospectionResults. This change is an attempt to fix the failing performance test case `testPrototypeCreationWithOverriddenResourcePropertiesIsFastEnough` in `AnnotationProcessorPerformanceTests`.
1 parent fd1b481 commit c2b56c0

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -490,18 +490,23 @@ private Object convertIfNecessary(String propertyName, Object oldValue, Object n
490490
* @throws TypeMismatchException if type conversion failed
491491
*/
492492
public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException {
493-
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);
493+
CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
494+
PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
495+
TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
494496
if (pd == null) {
495497
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
496498
"No property '" + propertyName + "' found");
497499
}
498-
return convertForProperty(propertyName, null, value, pd);
500+
if (td == null) {
501+
td = new TypeDescriptor(property(pd));
502+
cachedIntrospectionResults.putTypeDescriptor(pd, td);
503+
}
504+
return convertForProperty(propertyName, null, value, pd, td);
499505
}
500506

501-
private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd)
507+
private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd, TypeDescriptor td)
502508
throws TypeMismatchException {
503-
504-
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), new TypeDescriptor(property(pd)));
509+
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), td);
505510
}
506511

507512
private Property property(PropertyDescriptor pd) {
@@ -1107,7 +1112,7 @@ public Object run() throws Exception {
11071112
}
11081113
}
11091114
}
1110-
valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);
1115+
valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd, new TypeDescriptor(property(pd)));
11111116
}
11121117
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
11131118
}

spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.beans.PropertyDescriptor;
2323
import java.lang.ref.Reference;
2424
import java.lang.ref.WeakReference;
25+
import java.util.HashMap;
2526
import java.util.HashSet;
2627
import java.util.Iterator;
2728
import java.util.LinkedHashMap;
@@ -32,6 +33,7 @@
3233

3334
import org.apache.commons.logging.Log;
3435
import org.apache.commons.logging.LogFactory;
36+
import org.springframework.core.convert.TypeDescriptor;
3537
import org.springframework.core.io.support.SpringFactoriesLoader;
3638
import org.springframework.util.ClassUtils;
3739
import org.springframework.util.StringUtils;
@@ -216,6 +218,9 @@ private static boolean isUnderneathClassLoader(ClassLoader candidate, ClassLoade
216218
/** PropertyDescriptor objects keyed by property name String */
217219
private final Map<String, PropertyDescriptor> propertyDescriptorCache;
218220

221+
/** TypeDescriptor objects keyed by PropertyDescriptor */
222+
private final Map<PropertyDescriptor, TypeDescriptor> typeDescriptorCache;
223+
219224

220225
/**
221226
* Create a new CachedIntrospectionResults instance for the given class.
@@ -273,6 +278,8 @@ private CachedIntrospectionResults(Class<?> beanClass) throws BeansException {
273278
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
274279
this.propertyDescriptorCache.put(pd.getName(), pd);
275280
}
281+
282+
this.typeDescriptorCache = new HashMap<PropertyDescriptor, TypeDescriptor>();
276283
}
277284
catch (IntrospectionException ex) {
278285
throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);
@@ -321,4 +328,12 @@ private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class<?> bean
321328
}
322329
}
323330

331+
TypeDescriptor getTypeDescriptor(PropertyDescriptor pd) {
332+
return this.typeDescriptorCache.get(pd);
333+
}
334+
335+
void putTypeDescriptor(PropertyDescriptor pd, TypeDescriptor td) {
336+
this.typeDescriptorCache.put(pd, td);
337+
}
338+
324339
}

0 commit comments

Comments
 (0)