|
|
@ -278,79 +278,85 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp |
|
|
|
markBeanAsCreated(beanName); |
|
|
|
markBeanAsCreated(beanName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); |
|
|
|
try { |
|
|
|
checkMergedBeanDefinition(mbd, beanName, args); |
|
|
|
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); |
|
|
|
|
|
|
|
checkMergedBeanDefinition(mbd, beanName, args); |
|
|
|
// Guarantee initialization of beans that the current bean depends on.
|
|
|
|
|
|
|
|
String[] dependsOn = mbd.getDependsOn(); |
|
|
|
// Guarantee initialization of beans that the current bean depends on.
|
|
|
|
if (dependsOn != null) { |
|
|
|
String[] dependsOn = mbd.getDependsOn(); |
|
|
|
for (String dependsOnBean : dependsOn) { |
|
|
|
if (dependsOn != null) { |
|
|
|
getBean(dependsOnBean); |
|
|
|
for (String dependsOnBean : dependsOn) { |
|
|
|
registerDependentBean(dependsOnBean, beanName); |
|
|
|
getBean(dependsOnBean); |
|
|
|
} |
|
|
|
registerDependentBean(dependsOnBean, beanName); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create bean instance.
|
|
|
|
|
|
|
|
if (mbd.isSingleton()) { |
|
|
|
|
|
|
|
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Object getObject() throws BeansException { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
return createBean(beanName, mbd, args); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (BeansException ex) { |
|
|
|
|
|
|
|
// Explicitly remove instance from singleton cache: It might have been put there
|
|
|
|
|
|
|
|
// eagerly by the creation process, to allow for circular reference resolution.
|
|
|
|
|
|
|
|
// Also remove any beans that received a temporary reference to the bean.
|
|
|
|
|
|
|
|
destroySingleton(beanName); |
|
|
|
|
|
|
|
throw ex; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else if (mbd.isPrototype()) { |
|
|
|
|
|
|
|
// It's a prototype -> create a new instance.
|
|
|
|
|
|
|
|
Object prototypeInstance = null; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
beforePrototypeCreation(beanName); |
|
|
|
|
|
|
|
prototypeInstance = createBean(beanName, mbd, args); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
finally { |
|
|
|
|
|
|
|
afterPrototypeCreation(beanName); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else { |
|
|
|
// Create bean instance.
|
|
|
|
String scopeName = mbd.getScope(); |
|
|
|
if (mbd.isSingleton()) { |
|
|
|
final Scope scope = this.scopes.get(scopeName); |
|
|
|
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { |
|
|
|
if (scope == null) { |
|
|
|
|
|
|
|
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { |
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Object getObject() throws BeansException { |
|
|
|
public Object getObject() throws BeansException { |
|
|
|
beforePrototypeCreation(beanName); |
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
return createBean(beanName, mbd, args); |
|
|
|
return createBean(beanName, mbd, args); |
|
|
|
} |
|
|
|
} |
|
|
|
finally { |
|
|
|
catch (BeansException ex) { |
|
|
|
afterPrototypeCreation(beanName); |
|
|
|
// Explicitly remove instance from singleton cache: It might have been put there
|
|
|
|
|
|
|
|
// eagerly by the creation process, to allow for circular reference resolution.
|
|
|
|
|
|
|
|
// Also remove any beans that received a temporary reference to the bean.
|
|
|
|
|
|
|
|
destroySingleton(beanName); |
|
|
|
|
|
|
|
throw ex; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); |
|
|
|
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (IllegalStateException ex) { |
|
|
|
|
|
|
|
throw new BeanCreationException(beanName, |
|
|
|
else if (mbd.isPrototype()) { |
|
|
|
"Scope '" + scopeName + "' is not active for the current thread; " + |
|
|
|
// It's a prototype -> create a new instance.
|
|
|
|
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", |
|
|
|
Object prototypeInstance = null; |
|
|
|
ex); |
|
|
|
try { |
|
|
|
|
|
|
|
beforePrototypeCreation(beanName); |
|
|
|
|
|
|
|
prototypeInstance = createBean(beanName, mbd, args); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
finally { |
|
|
|
|
|
|
|
afterPrototypeCreation(beanName); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
String scopeName = mbd.getScope(); |
|
|
|
|
|
|
|
final Scope scope = this.scopes.get(scopeName); |
|
|
|
|
|
|
|
if (scope == null) { |
|
|
|
|
|
|
|
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Object getObject() throws BeansException { |
|
|
|
|
|
|
|
beforePrototypeCreation(beanName); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
return createBean(beanName, mbd, args); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
finally { |
|
|
|
|
|
|
|
afterPrototypeCreation(beanName); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (IllegalStateException ex) { |
|
|
|
|
|
|
|
throw new BeanCreationException(beanName, |
|
|
|
|
|
|
|
"Scope '" + scopeName + "' is not active for the current thread; " + |
|
|
|
|
|
|
|
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", |
|
|
|
|
|
|
|
ex); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
catch (BeansException ex) { |
|
|
|
|
|
|
|
cleanupAfterBeanCreationFailure(beanName); |
|
|
|
|
|
|
|
throw ex; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Check if required type matches the type of the actual bean instance.
|
|
|
|
// Check if required type matches the type of the actual bean instance.
|
|
|
@ -1430,6 +1436,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp |
|
|
|
this.alreadyCreated.add(beanName); |
|
|
|
this.alreadyCreated.add(beanName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Perform appropriate cleanup of cached metadata after bean creation failed. |
|
|
|
|
|
|
|
* @param beanName the name of the bean |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected void cleanupAfterBeanCreationFailure(String beanName) { |
|
|
|
|
|
|
|
this.alreadyCreated.remove(beanName); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Determine whether the specified bean is eligible for having |
|
|
|
* Determine whether the specified bean is eligible for having |
|
|
|
* its bean definition metadata cached. |
|
|
|
* its bean definition metadata cached. |
|
|
|