diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
index f8d38a93bf3..37e5d98fc68 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
@@ -880,8 +880,18 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
// Shortcut when re-creating the same bean...
- if (mbd.resolvedConstructorOrFactoryMethod != null && args == null) {
- if (mbd.constructorArgumentsResolved) {
+ boolean resolved = false;
+ boolean autowireNecessary = false;
+ if (args == null) {
+ synchronized (mbd.constructorArgumentLock) {
+ if (mbd.resolvedConstructorOrFactoryMethod != null) {
+ resolved = true;
+ autowireNecessary = mbd.constructorArgumentsResolved;
+ }
+ }
+ }
+ if (resolved) {
+ if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
index 84052539489..b464238572b 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
@@ -117,14 +117,20 @@ class ConstructorResolver {
argsToUse = explicitArgs;
}
else {
- constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
- if (constructorToUse != null) {
- // Found a cached constructor...
- argsToUse = mbd.resolvedConstructorArguments;
- if (argsToUse == null) {
- argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse);
+ Object[] argsToResolve = null;
+ synchronized (mbd.constructorArgumentLock) {
+ constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
+ if (constructorToUse != null && mbd.constructorArgumentsResolved) {
+ // Found a cached constructor...
+ argsToUse = mbd.resolvedConstructorArguments;
+ if (argsToUse == null) {
+ argsToResolve = mbd.preparedConstructorArguments;
+ }
}
}
+ if (argsToResolve != null) {
+ argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
+ }
}
if (constructorToUse == null) {
@@ -254,8 +260,7 @@ class ConstructorResolver {
}
if (explicitArgs == null) {
- mbd.resolvedConstructorOrFactoryMethod = constructorToUse;
- argsHolderToUse.storeCache(mbd);
+ argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
@@ -312,7 +317,9 @@ class ConstructorResolver {
}
}
}
- mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
+ synchronized (mbd.constructorArgumentLock) {
+ mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
+ }
}
/**
@@ -371,14 +378,20 @@ class ConstructorResolver {
argsToUse = explicitArgs;
}
else {
- factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
- if (factoryMethodToUse != null) {
- // Found a cached factory method...
- argsToUse = mbd.resolvedConstructorArguments;
- if (argsToUse == null && mbd.preparedConstructorArguments != null) {
- argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse);
+ Object[] argsToResolve = null;
+ synchronized (mbd.constructorArgumentLock) {
+ factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
+ if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
+ // Found a cached factory method...
+ argsToUse = mbd.resolvedConstructorArguments;
+ if (argsToUse == null) {
+ argsToResolve = mbd.preparedConstructorArguments;
+ }
}
}
+ if (argsToResolve != null) {
+ argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
+ }
}
if (factoryMethodToUse == null || argsToUse == null) {
@@ -536,8 +549,7 @@ class ConstructorResolver {
}
if (explicitArgs == null) {
- mbd.resolvedConstructorOrFactoryMethod = factoryMethodToUse;
- argsHolderToUse.storeCache(mbd);
+ argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
@@ -734,11 +746,10 @@ class ConstructorResolver {
* Resolve the prepared arguments stored in the given bean definition.
*/
private Object[] resolvePreparedArguments(
- String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor) {
+ String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
Class[] paramTypes = (methodOrCtor instanceof Method ?
((Method) methodOrCtor).getParameterTypes() : ((Constructor) methodOrCtor).getParameterTypes());
- Object[] argsToResolve = mbd.preparedConstructorArguments;
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
BeanDefinitionValueResolver valueResolver =
@@ -789,11 +800,11 @@ class ConstructorResolver {
*/
private static class ArgumentsHolder {
- public Object rawArguments[];
+ public final Object rawArguments[];
- public Object arguments[];
+ public final Object arguments[];
- public Object preparedArguments[];
+ public final Object preparedArguments[];
public boolean resolveNecessary = false;
@@ -833,14 +844,17 @@ class ConstructorResolver {
return Integer.MAX_VALUE - 1024;
}
- public void storeCache(RootBeanDefinition mbd) {
- if (this.resolveNecessary) {
- mbd.preparedConstructorArguments = this.preparedArguments;
+ public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) {
+ synchronized (mbd.constructorArgumentLock) {
+ mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
+ mbd.constructorArgumentsResolved = true;
+ if (this.resolveNecessary) {
+ mbd.preparedConstructorArguments = this.preparedArguments;
+ }
+ else {
+ mbd.resolvedConstructorArguments = this.arguments;
+ }
}
- else {
- mbd.resolvedConstructorArguments = this.arguments;
- }
- mbd.constructorArgumentsResolved = true;
}
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
index 70b00637043..cabc026e12a 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
@@ -504,8 +504,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
*/
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor) {
resolveBeanClass(mbd, beanName);
- if (mbd.isFactoryMethodUnique && mbd.resolvedConstructorOrFactoryMethod == null) {
- new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
+ if (mbd.isFactoryMethodUnique) {
+ boolean resolve;
+ synchronized (mbd.constructorArgumentLock) {
+ resolve = (mbd.resolvedConstructorOrFactoryMethod == null);
+ }
+ if (resolve) {
+ new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
+ }
}
return getAutowireCandidateResolver().isAutowireCandidate(
new BeanDefinitionHolder(mbd, beanName, getAliases(beanName)), descriptor);
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
index 5dc0dd0d717..39e2915fa37 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
@@ -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.
@@ -59,16 +59,18 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
boolean isFactoryMethodUnique;
/** Package-visible field for caching the resolved constructor or factory method */
- volatile Object resolvedConstructorOrFactoryMethod;
-
- /** Package-visible field for caching fully resolved constructor arguments */
- volatile Object[] resolvedConstructorArguments;
-
- /** Package-visible field for caching partly prepared constructor arguments */
- volatile Object[] preparedConstructorArguments;
+ Object resolvedConstructorOrFactoryMethod;
/** Package-visible field that marks the constructor arguments as resolved */
- volatile boolean constructorArgumentsResolved = false;
+ boolean constructorArgumentsResolved = false;
+
+ /** Package-visible field for caching fully resolved constructor arguments */
+ Object[] resolvedConstructorArguments;
+
+ /** Package-visible field for caching partly prepared constructor arguments */
+ Object[] preparedConstructorArguments;
+
+ final Object constructorArgumentLock = new Object();
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
volatile Boolean beforeInstantiationResolved;
@@ -78,6 +80,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
final Object postProcessingLock = new Object();
+
/**
* Create a new RootBeanDefinition, to be configured through its bean
* properties and configuration methods.
@@ -264,8 +267,10 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
* @return the factory method, or null if not found or not resolved yet
*/
public Method getResolvedFactoryMethod() {
- Object candidate = this.resolvedConstructorOrFactoryMethod;
- return (candidate instanceof Method ? (Method) candidate : null);
+ synchronized (this.constructorArgumentLock) {
+ Object candidate = this.resolvedConstructorOrFactoryMethod;
+ return (candidate instanceof Method ? (Method) candidate : null);
+ }
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java
index cfba4262933..ba0906219fb 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java
@@ -45,27 +45,30 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (beanDefinition.getMethodOverrides().isEmpty()) {
- Constructor> constructorToUse = (Constructor>) beanDefinition.resolvedConstructorOrFactoryMethod;
- if (constructorToUse == null) {
- final Class clazz = beanDefinition.getBeanClass();
- if (clazz.isInterface()) {
- throw new BeanInstantiationException(clazz, "Specified class is an interface");
- }
- try {
- if (System.getSecurityManager() != null) {
- constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction() {
- public Constructor run() throws Exception {
- return clazz.getDeclaredConstructor((Class[]) null);
- }
- });
+ Constructor> constructorToUse;
+ synchronized (beanDefinition.constructorArgumentLock) {
+ constructorToUse = (Constructor>) beanDefinition.resolvedConstructorOrFactoryMethod;
+ if (constructorToUse == null) {
+ final Class clazz = beanDefinition.getBeanClass();
+ if (clazz.isInterface()) {
+ throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
- else {
- constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
+ try {
+ if (System.getSecurityManager() != null) {
+ constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Constructor run() throws Exception {
+ return clazz.getDeclaredConstructor((Class[]) null);
+ }
+ });
+ }
+ else {
+ constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
+ }
+ beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
+ }
+ catch (Exception ex) {
+ throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
- beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
- }
- catch (Exception ex) {
- throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
return BeanUtils.instantiateClass(constructorToUse);