initialize cache Maps early, turning them into final fields
This commit is contained in:
parent
7553b76f15
commit
5be9473136
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue