Browse Source

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`.
pull/423/head
Phillip Webb 11 years ago
parent
commit
c2b56c07e5
  1. 17
      spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java
  2. 15
      spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java

17
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 * @throws TypeMismatchException if type conversion failed
*/ */
public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException { 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) { if (pd == null) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"No property '" + propertyName + "' found"); "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 { throws TypeMismatchException {
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), td);
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), new TypeDescriptor(property(pd)));
} }
private Property property(PropertyDescriptor pd) { 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); pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
} }

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

@ -22,6 +22,7 @@ import java.beans.Introspector;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.lang.ref.Reference; import java.lang.ref.Reference;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -32,6 +33,7 @@ import java.util.WeakHashMap;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -216,6 +218,9 @@ public class CachedIntrospectionResults {
/** PropertyDescriptor objects keyed by property name String */ /** PropertyDescriptor objects keyed by property name String */
private final Map<String, PropertyDescriptor> propertyDescriptorCache; private final Map<String, PropertyDescriptor> propertyDescriptorCache;
/** TypeDescriptor objects keyed by PropertyDescriptor */
private final Map<PropertyDescriptor, TypeDescriptor> typeDescriptorCache;
/** /**
* Create a new CachedIntrospectionResults instance for the given class. * Create a new CachedIntrospectionResults instance for the given class.
@ -273,6 +278,8 @@ public class CachedIntrospectionResults {
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd); pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
this.propertyDescriptorCache.put(pd.getName(), pd); this.propertyDescriptorCache.put(pd.getName(), pd);
} }
this.typeDescriptorCache = new HashMap<PropertyDescriptor, TypeDescriptor>();
} }
catch (IntrospectionException ex) { catch (IntrospectionException ex) {
throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", 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);
}
} }

Loading…
Cancel
Save