fixed potential race condition through additional synchronization (SPR-5658)

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1069 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Juergen Hoeller 2009-04-27 22:53:40 +00:00
parent 6c3dd342fe
commit d7836b9fcc
1 changed files with 98 additions and 79 deletions

View File

@ -396,6 +396,23 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
}
/**
* Resolve the specified cached method argument or field value.
*/
private Object resolvedCachedArgument(String beanName, Object cachedArgument) {
if (cachedArgument instanceof DependencyDescriptor) {
DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
TypeConverter typeConverter = beanFactory.getTypeConverter();
return beanFactory.resolveDependency(descriptor, beanName, null, typeConverter);
}
else if (cachedArgument instanceof RuntimeBeanReference) {
return beanFactory.getBean(((RuntimeBeanReference) cachedArgument).getBeanName());
}
else {
return cachedArgument;
}
}
/**
* Class representing injection information about an annotated field.
@ -419,19 +436,11 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
try {
Object value;
if (this.cached) {
if (this.cachedFieldValue instanceof DependencyDescriptor) {
DependencyDescriptor descriptor = (DependencyDescriptor) this.cachedFieldValue;
TypeConverter typeConverter = beanFactory.getTypeConverter();
value = beanFactory.resolveDependency(descriptor, beanName, null, typeConverter);
}
else if (this.cachedFieldValue instanceof RuntimeBeanReference) {
value = beanFactory.getBean(((RuntimeBeanReference) this.cachedFieldValue).getBeanName());
}
else {
value = this.cachedFieldValue;
}
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
synchronized (this) {
if (!this.cached) {
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required);
@ -453,6 +462,12 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
this.cached = true;
}
else {
// Already cached in the meantime...
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
@ -492,27 +507,14 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
Method method = (Method) this.member;
try {
Object[] arguments = null;
Object[] arguments;
if (this.cached) {
if (this.cachedMethodArguments != null) {
arguments = new Object[this.cachedMethodArguments.length];
for (int i = 0; i < arguments.length; i++) {
Object cachedArg = this.cachedMethodArguments[i];
if (cachedArg instanceof DependencyDescriptor) {
DependencyDescriptor descriptor = (DependencyDescriptor) cachedArg;
TypeConverter typeConverter = beanFactory.getTypeConverter();
arguments[i] = beanFactory.resolveDependency(descriptor, beanName, null, typeConverter);
}
else if (cachedArg instanceof RuntimeBeanReference) {
arguments[i] = beanFactory.getBean(((RuntimeBeanReference) cachedArg).getBeanName());
}
else {
arguments[i] = cachedArg;
}
}
}
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
synchronized (this) {
if (!this.cached) {
Class[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
Set<String> autowiredBeanNames = new LinkedHashSet<String>(arguments.length);
@ -552,6 +554,12 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
this.cached = true;
}
else {
// Already cached in the meantime...
arguments = resolveCachedArguments(beanName);
}
}
}
if (this.skip == null) {
if (this.pd != null && pvs instanceof MutablePropertyValues) {
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
@ -570,6 +578,17 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
throw new BeanCreationException("Could not autowire method: " + method, ex);
}
}
private Object[] resolveCachedArguments(String beanName) {
if (this.cachedMethodArguments == null) {
return null;
}
Object[] arguments = new Object[this.cachedMethodArguments.length];
for (int i = 0; i < arguments.length; i++) {
arguments[i] = resolvedCachedArgument(beanName, this.cachedMethodArguments[i]);
}
return arguments;
}
}
}