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 056b88b587..ef51e90b22 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java @@ -480,8 +480,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra } TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd); if (td == null) { - td = new TypeDescriptor(property(pd)); - cachedIntrospectionResults.addTypeDescriptor(pd, td); + td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd))); } return convertForProperty(propertyName, null, value, td); } 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 a74017dca7..4066c28045 100644 --- a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java +++ b/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -112,14 +113,14 @@ public class CachedIntrospectionResults { * Map keyed by Class containing CachedIntrospectionResults, strongly held. * This variant is being used for cache-safe bean classes. */ - static final Map, CachedIntrospectionResults> strongClassCache = + static final ConcurrentMap, CachedIntrospectionResults> strongClassCache = new ConcurrentHashMap, CachedIntrospectionResults>(64); /** * Map keyed by Class containing CachedIntrospectionResults, softly held. * This variant is being used for non-cache-safe bean classes. */ - static final Map, CachedIntrospectionResults> softClassCache = + static final ConcurrentMap, CachedIntrospectionResults> softClassCache = new ConcurrentReferenceHashMap, CachedIntrospectionResults>(64); @@ -186,17 +187,21 @@ public class CachedIntrospectionResults { } results = new CachedIntrospectionResults(beanClass); + ConcurrentMap, CachedIntrospectionResults> classCacheToUse; + if (ClassUtils.isCacheSafe(beanClass, CachedIntrospectionResults.class.getClassLoader()) || isClassLoaderAccepted(beanClass.getClassLoader())) { - strongClassCache.putIfAbsent(beanClass, results); + classCacheToUse = strongClassCache; } else { if (logger.isDebugEnabled()) { logger.debug("Not strongly caching class [" + beanClass.getName() + "] because it is not cache-safe"); } - softClassCache.putIfAbsent(beanClass, results); + classCacheToUse = softClassCache; } - return results; + + CachedIntrospectionResults existing = classCacheToUse.putIfAbsent(beanClass, results); + return (existing != null ? existing : results); } /** @@ -246,7 +251,7 @@ public class CachedIntrospectionResults { private final Map propertyDescriptorCache; /** TypeDescriptor objects keyed by PropertyDescriptor */ - private final Map typeDescriptorCache; + private final ConcurrentMap typeDescriptorCache; /** @@ -295,7 +300,7 @@ public class CachedIntrospectionResults { "; editor [" + pd.getPropertyEditorClass().getName() + "]" : "")); } pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd); - this.propertyDescriptorCache.putIfAbsent(pd.getName(), pd); + this.propertyDescriptorCache.put(pd.getName(), pd); } this.typeDescriptorCache = new ConcurrentHashMap(); @@ -347,8 +352,9 @@ public class CachedIntrospectionResults { } } - void addTypeDescriptor(PropertyDescriptor pd, TypeDescriptor td) { - this.typeDescriptorCache.putIfAbsent(pd, td); + TypeDescriptor addTypeDescriptor(PropertyDescriptor pd, TypeDescriptor td) { + TypeDescriptor existing = this.typeDescriptorCache.putIfAbsent(pd, td); + return (existing != null ? existing : td); } TypeDescriptor getTypeDescriptor(PropertyDescriptor pd) {