From c2b56c07e59aeb123fbe63b282c0ef98d7380f56 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 2 Dec 2013 21:55:00 -0800 Subject: [PATCH] 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`. --- .../springframework/beans/BeanWrapperImpl.java | 17 +++++++++++------ .../beans/CachedIntrospectionResults.java | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java b/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java index 9f4b581a0e..35aa1a4278 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java @@ -490,18 +490,23 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra * @throws TypeMismatchException if type conversion failed */ public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException { - PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName); + CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults(); + PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName); + TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd); if (pd == null) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "No property '" + propertyName + "' found"); } - return convertForProperty(propertyName, null, value, pd); + if (td == null) { + td = new TypeDescriptor(property(pd)); + cachedIntrospectionResults.putTypeDescriptor(pd, td); + } + return convertForProperty(propertyName, null, value, pd, td); } - private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd) + private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd, TypeDescriptor td) throws TypeMismatchException { - - return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), new TypeDescriptor(property(pd))); + return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), td); } private Property property(PropertyDescriptor pd) { @@ -1107,7 +1112,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra } } } - valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd); + valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd, new TypeDescriptor(property(pd))); } pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue); } diff --git a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java b/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java index f57ce5c4e1..10dccab948 100644 --- a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java +++ b/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java @@ -22,6 +22,7 @@ import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; @@ -32,6 +33,7 @@ import java.util.WeakHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -216,6 +218,9 @@ public class CachedIntrospectionResults { /** PropertyDescriptor objects keyed by property name String */ private final Map propertyDescriptorCache; + /** TypeDescriptor objects keyed by PropertyDescriptor */ + private final Map typeDescriptorCache; + /** * Create a new CachedIntrospectionResults instance for the given class. @@ -273,6 +278,8 @@ public class CachedIntrospectionResults { pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd); this.propertyDescriptorCache.put(pd.getName(), pd); } + + this.typeDescriptorCache = new HashMap(); } catch (IntrospectionException ex) { throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex); @@ -321,4 +328,12 @@ public class CachedIntrospectionResults { } } + TypeDescriptor getTypeDescriptor(PropertyDescriptor pd) { + return this.typeDescriptorCache.get(pd); + } + + void putTypeDescriptor(PropertyDescriptor pd, TypeDescriptor td) { + this.typeDescriptorCache.put(pd, td); + } + }