initialize cache Maps early, turning them into final fields

This commit is contained in:
Juergen Hoeller 2010-10-10 20:11:44 +00:00
parent 7553b76f15
commit 5be9473136
1 changed files with 29 additions and 45 deletions

View File

@ -47,11 +47,12 @@ import org.springframework.util.StringUtils;
*/ */
public class ReflectivePropertyAccessor implements PropertyAccessor { public class ReflectivePropertyAccessor implements PropertyAccessor {
protected Map<CacheKey, InvokerPair> readerCache; protected final Map<CacheKey, InvokerPair> readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>();
protected Map<CacheKey, Member> writerCache; protected final Map<CacheKey, Member> writerCache = new ConcurrentHashMap<CacheKey, Member>();
protected final Map<CacheKey, TypeDescriptor> typeDescriptorCache = new ConcurrentHashMap<CacheKey, TypeDescriptor>();
protected Map<CacheKey, TypeDescriptor> typeDescriptorCache;
/** /**
* @return null which means this is a general purpose accessor * @return null which means this is a general purpose accessor
@ -65,15 +66,9 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return false; return false;
} }
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass());
if ((type.isArray() && name.equals("length"))) { if (type.isArray() && name.equals("length")) {
return true; return true;
} }
if (this.readerCache==null) {
this.readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>();
if (this.typeDescriptorCache == null) {
this.typeDescriptorCache = new ConcurrentHashMap<CacheKey,TypeDescriptor>();
}
}
CacheKey cacheKey = new CacheKey(type, name); CacheKey cacheKey = new CacheKey(type, name);
if (this.readerCache.containsKey(cacheKey)) { if (this.readerCache.containsKey(cacheKey)) {
return true; return true;
@ -119,14 +114,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return new TypedValue(Array.getLength(target),TypeDescriptor.valueOf(Integer.TYPE)); return new TypedValue(Array.getLength(target),TypeDescriptor.valueOf(Integer.TYPE));
} }
if (this.readerCache==null) {
this.readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>();
}
CacheKey cacheKey = new CacheKey(type, name); CacheKey cacheKey = new CacheKey(type, name);
InvokerPair invoker = this.readerCache.get(cacheKey); InvokerPair invoker = this.readerCache.get(cacheKey);
if (invoker == null || invoker.member instanceof Method) { if (invoker == null || invoker.member instanceof Method) {
Method method = (Method) (invoker==null?null:invoker.member); Method method = (Method) (invoker != null ? invoker.member : null);
if (method == null) { if (method == null) {
method = findGetterForProperty(name, type, target instanceof Class); method = findGetterForProperty(name, type, target instanceof Class);
if (method != null) { if (method != null) {
@ -185,12 +177,6 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return false; return false;
} }
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass());
if (this.writerCache == null) {
this.writerCache = new ConcurrentHashMap<CacheKey, Member>();
if (this.typeDescriptorCache == null) {
this.typeDescriptorCache = new ConcurrentHashMap<CacheKey,TypeDescriptor>();
}
}
CacheKey cacheKey = new CacheKey(type, name); CacheKey cacheKey = new CacheKey(type, name);
if (this.writerCache.containsKey(cacheKey)) { if (this.writerCache.containsKey(cacheKey)) {
return true; return true;
@ -201,7 +187,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
PropertyDescriptor propertyDescriptor = null; PropertyDescriptor propertyDescriptor = null;
try { try {
propertyDescriptor = new PropertyDescriptor(name,null,method); propertyDescriptor = new PropertyDescriptor(name,null,method);
} catch (IntrospectionException ex) { }
catch (IntrospectionException ex) {
throw new AccessException("Unable to access property '" + name + "' through setter "+method, ex); throw new AccessException("Unable to access property '" + name + "' through setter "+method, ex);
} }
MethodParameter mp = new MethodParameter(method,0); MethodParameter mp = new MethodParameter(method,0);
@ -232,13 +219,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
if (typeDescriptor != null) { if (typeDescriptor != null) {
try { try {
possiblyConvertedNewValue = context.getTypeConverter().convertValue(newValue, TypeDescriptor.forObject(newValue), typeDescriptor); possiblyConvertedNewValue = context.getTypeConverter().convertValue(newValue, TypeDescriptor.forObject(newValue), typeDescriptor);
} catch (EvaluationException evaluationException) { }
catch (EvaluationException evaluationException) {
throw new AccessException("Type conversion failure",evaluationException); throw new AccessException("Type conversion failure",evaluationException);
} }
} }
if (this.writerCache == null) {
this.writerCache = new ConcurrentHashMap<CacheKey, Member>();
}
CacheKey cacheKey = new CacheKey(type, name); CacheKey cacheKey = new CacheKey(type, name);
Member cachedMember = this.writerCache.get(cacheKey); Member cachedMember = this.writerCache.get(cacheKey);
@ -303,11 +288,13 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
try { try {
if (canRead(context, target, name)) { if (canRead(context, target, name)) {
typeDescriptor = this.typeDescriptorCache.get(cacheKey); typeDescriptor = this.typeDescriptorCache.get(cacheKey);
} else if (canWrite(context, target, name)) { }
else if (canWrite(context, target, name)) {
typeDescriptor = this.typeDescriptorCache.get(cacheKey); typeDescriptor = this.typeDescriptorCache.get(cacheKey);
} }
} catch (AccessException e) { }
// continue with null typeDescriptor catch (AccessException ex) {
// continue with null type descriptor
} }
} }
return typeDescriptor; return typeDescriptor;
@ -422,7 +409,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
*/ */
public PropertyAccessor createOptimalAccessor(EvaluationContext eContext, Object target, String name) { public PropertyAccessor createOptimalAccessor(EvaluationContext eContext, Object target, String name) {
// Don't be clever for arrays or null target // Don't be clever for arrays or null target
if (target==null) { if (target == null) {
return this; return this;
} }
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass()); Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass());
@ -431,12 +418,6 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
} }
CacheKey cacheKey = new CacheKey(type, name); CacheKey cacheKey = new CacheKey(type, name);
if (this.readerCache==null) {
this.readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>();
if (this.typeDescriptorCache == null) {
this.typeDescriptorCache = new ConcurrentHashMap<CacheKey,TypeDescriptor>();
}
}
InvokerPair invocationTarget = this.readerCache.get(cacheKey); InvokerPair invocationTarget = this.readerCache.get(cacheKey);
if (invocationTarget == null || invocationTarget.member instanceof Method) { if (invocationTarget == null || invocationTarget.member instanceof Method) {
@ -489,7 +470,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
Field field = (Field)member; Field field = (Field)member;
needsToBeMadeAccessible = (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) needsToBeMadeAccessible = (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()))
&& !field.isAccessible(); && !field.isAccessible();
} else { }
else {
Method method = (Method)member; Method method = (Method)member;
needsToBeMadeAccessible = ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) needsToBeMadeAccessible = ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()); && !method.isAccessible());
@ -516,7 +498,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
} }
getterName = "is" + StringUtils.capitalize(name); getterName = "is" + StringUtils.capitalize(name);
return getterName.equals(method.getName()); return getterName.equals(method.getName());
} else { }
else {
Field field = (Field)member; Field field = (Field)member;
return field.getName().equals(name); return field.getName().equals(name);
} }
@ -526,11 +509,12 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
if (member instanceof Method) { if (member instanceof Method) {
try { try {
if (needsToBeMadeAccessible) { if (needsToBeMadeAccessible) {
ReflectionUtils.makeAccessible((Method)member); ReflectionUtils.makeAccessible((Method) member);
} }
return new TypedValue(((Method)member).invoke(target),typeDescriptor); return new TypedValue(((Method) member).invoke(target), typeDescriptor);
} catch (Exception e) { }
throw new AccessException("Unable to access property '" + name + "' through getter", e); catch (Exception ex) {
throw new AccessException("Unable to access property '" + name + "' through getter", ex);
} }
} }
if (member instanceof Field) { if (member instanceof Field) {
@ -555,6 +539,6 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
throws AccessException { throws AccessException {
throw new UnsupportedOperationException("Should not be called on an OptimalPropertyAccessor"); throw new UnsupportedOperationException("Should not be called on an OptimalPropertyAccessor");
} }
} }
} }