Use ConcurrentMap declarations when calling putIfAbsent (for compatibility with JDK 6 and 7)

Issue: SPR-12102
This commit is contained in:
Juergen Hoeller 2014-08-19 23:28:42 +02:00
parent 781a6d289e
commit af6ef5f74c
2 changed files with 16 additions and 11 deletions

View File

@ -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);
}

View File

@ -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<Class<?>, CachedIntrospectionResults> strongClassCache =
static final ConcurrentMap<Class<?>, CachedIntrospectionResults> strongClassCache =
new ConcurrentHashMap<Class<?>, CachedIntrospectionResults>(64);
/**
* Map keyed by Class containing CachedIntrospectionResults, softly held.
* This variant is being used for non-cache-safe bean classes.
*/
static final Map<Class<?>, CachedIntrospectionResults> softClassCache =
static final ConcurrentMap<Class<?>, CachedIntrospectionResults> softClassCache =
new ConcurrentReferenceHashMap<Class<?>, CachedIntrospectionResults>(64);
@ -186,17 +187,21 @@ public class CachedIntrospectionResults {
}
results = new CachedIntrospectionResults(beanClass);
ConcurrentMap<Class<?>, 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<String, PropertyDescriptor> propertyDescriptorCache;
/** TypeDescriptor objects keyed by PropertyDescriptor */
private final Map<PropertyDescriptor, TypeDescriptor> typeDescriptorCache;
private final ConcurrentMap<PropertyDescriptor, TypeDescriptor> 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<PropertyDescriptor, TypeDescriptor>();
@ -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) {