fixed concurrency issue in TypedStringValue, showing for nested typed Maps in prototype beans (SPR-7398); optimized building of keyed arg names in BeanDefinitionValueResolver

This commit is contained in:
Juergen Hoeller 2010-07-29 13:49:09 +00:00
parent bd4f4d0d30
commit c3a639f07d
2 changed files with 36 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -38,7 +38,7 @@ public class TypedStringValue implements BeanMetadataElement {
private String value;
private Object targetType;
private volatile Object targetType;
private Object source;
@ -110,10 +110,11 @@ public class TypedStringValue implements BeanMetadataElement {
* Return the type to convert to.
*/
public Class getTargetType() {
if (!(this.targetType instanceof Class)) {
Object targetTypeValue = this.targetType;
if (!(targetTypeValue instanceof Class)) {
throw new IllegalStateException("Typed String value does not carry a resolved target type");
}
return (Class) this.targetType;
return (Class) targetTypeValue;
}
/**
@ -128,11 +129,12 @@ public class TypedStringValue implements BeanMetadataElement {
* Return the type to convert to.
*/
public String getTargetTypeName() {
if (this.targetType instanceof Class) {
return ((Class) this.targetType).getName();
Object targetTypeValue = this.targetType;
if (targetTypeValue instanceof Class) {
return ((Class) targetTypeValue).getName();
}
else {
return (String) this.targetType;
return (String) targetTypeValue;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -338,9 +338,7 @@ class BeanDefinitionValueResolver {
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
Array.set(resolved, i,
resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
@ -352,9 +350,7 @@ class BeanDefinitionValueResolver {
List<Object> resolved = new ArrayList<Object>(ml.size());
for (int i = 0; i < ml.size(); i++) {
resolved.add(
resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
@ -366,8 +362,7 @@ class BeanDefinitionValueResolver {
Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
int i = 0;
for (Object m : ms) {
resolved.add(resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX, m));
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));
i++;
}
return resolved;
@ -381,11 +376,32 @@ class BeanDefinitionValueResolver {
for (Map.Entry entry : mm.entrySet()) {
Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
Object resolvedValue = resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + entry.getKey() +
BeanWrapper.PROPERTY_KEY_SUFFIX, entry.getValue());
new KeyedArgName(argName, entry.getKey()), entry.getValue());
resolved.put(resolvedKey, resolvedValue);
}
return resolved;
}
/**
* Holder class used for delayed toString building.
*/
private static class KeyedArgName {
private final Object argName;
private final Object key;
public KeyedArgName(Object argName, Object key) {
this.argName = argName;
this.key = key;
}
@Override
public String toString() {
return this.argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX +
this.key + BeanWrapper.PROPERTY_KEY_SUFFIX;
}
}
}