📄 abstractautowirecapablebeanfactory.java
字号:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
throws BeanCreationException {
// Guarantee initialization of beans that the current one depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (int i = 0; i < dependsOn.length; i++) {
getBean(dependsOn[i]);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "' with merged definition [" + mbd + "]");
}
// Make sure bean class is actually resolved at this point.
Class beanClass = resolveBeanClass(mbd, beanName);
// Prepare method overrides.
try {
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
String errorMessage = null;
try {
// Instantiate the bean.
errorMessage = "BeanPostProcessor before instantiation of bean failed";
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
if (beanClass != null &&
!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Object bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
return bean;
}
}
// Instantiate the bean.
errorMessage = "Instantiation of bean failed";
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
synchronized (getSingletonMutex()) {
instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
}
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
if (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName)) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingleton(beanName, bean);
}
// Initialize the bean instance.
errorMessage = "Initialization of bean failed";
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
if (!ibp.postProcessAfterInstantiation(bean, beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (continueWithPropertyPopulation) {
populateBean(beanName, mbd, instanceWrapper);
}
Object originalBean = bean;
bean = initializeBean(beanName, bean, mbd);
if (!this.allowRawInjectionDespiteWrapping && originalBean != bean &&
mbd.isSingleton() && hasDependentBean(beanName)) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans " +
getDependentBeans(beanName) + " in its raw version as part of a circular reference, " +
"but has eventually been wrapped (for example as part of auto-proxy creation). " +
"This means that said other beans do not use the final version of the bean. " +
"This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
// Register bean as disposable, and also as dependent on specified "dependsOn" beans.
registerDisposableBeanIfNecessary(beanName, originalBean, mbd);
return bean;
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, errorMessage, ex);
}
}
}
/**
* Predict the eventual bean type for the given bean.
* @param beanName the name of the bean
* @param mbd the merged bean definition to determine the type for
* @return the type of the bean, or <code>null</code> if not predictable
*/
protected Class predictBeanType(String beanName, RootBeanDefinition mbd) {
Class beanClass = null;
if (mbd.getFactoryMethodName() != null) {
beanClass = getTypeForFactoryMethod(beanName, mbd);
}
else {
beanClass = resolveBeanClass(mbd, beanName);
}
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
// eventual type after a before-instantiation shortcut.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
BeanPostProcessor bp = (BeanPostProcessor) it.next();
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Class processedType = ibp.predictBeanType(beanClass, beanName);
if (processedType != null) {
return processedType;
}
}
}
}
return beanClass;
}
/**
* Determine the bean type for the given bean definition which is based on
* a factory method. Only called if there is no singleton instance registered
* for the target bean already.
* <p>This implementation determines the type matching {@link #createBean}'s
* different creation strategies. As far as possible, we'll perform static
* type checking to avoid creation of the target bean.
* @param beanName the name of the bean (for error handling purposes)
* @param mbd the merged bean definition for the bean
* @return the type for the bean if determinable, or <code>null</code> else
* @see #createBean
*/
protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd) {
Class factoryClass = null;
boolean isStatic = true;
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// Check declared factory method return type on factory class.
factoryClass = getType(factoryBeanName);
isStatic = false;
}
else {
// Check declared factory method return type on bean class.
factoryClass = resolveBeanClass(mbd, beanName);
}
if (factoryClass == null) {
return null;
}
// If all factory methods have the same return type, return that type.
// Can't clearly figure out exact method due to type converting / autowiring!
int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
Set returnTypes = new HashSet(1);
for (int i = 0; i < candidates.length; i++) {
Method factoryMethod = candidates[i];
if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic &&
factoryMethod.getName().equals(mbd.getFactoryMethodName()) &&
factoryMethod.getParameterTypes().length >= minNrOfArgs) {
returnTypes.add(factoryMethod.getReturnType());
}
}
if (returnTypes.size() == 1) {
// Clear return type found: all factory methods return same type.
return (Class) returnTypes.iterator().next();
}
else {
// Ambiguous return types found: return null to indicate "not determinable".
return null;
}
}
/**
* This implementation checks the FactoryBean's <code>getObjectType</code> method
* on a plain instance of the FactoryBean, without bean properties applied yet.
* If this doesn't return a type yet, a full creation of the FactoryBean is
* used as fallback (through delegation to the superclass's implementation).
* <p>The shortcut check for a FactoryBean is only applied in case of a singleton
* FactoryBean. If the FactoryBean instance itself is not kept as singleton,
* it will be fully created to check the type of its exposed object.
*/
protected Class getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
FactoryBean fb = (mbd.isSingleton() ?
getSingletonFactoryBeanForTypeCheck(beanName, mbd) :
getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
if (fb != null) {
// Try to obtain the FactoryBean's object type from this early stage of the instance.
Class objectType = getTypeForFactoryBean(fb);
if (objectType != null) {
return objectType;
}
}
// No type found - fall back to full creation of the FactoryBean instance.
return super.getTypeForFactoryBean(beanName, mbd);
}
//---------------------------------------------------------------------
// Implementation methods
//---------------------------------------------------------------------
/**
* Obtain a "shortcut" singleton FactoryBean instance to use for a
* <code>getObjectType()</code> call, without full initialization
* of the FactoryBean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the FactoryBean instance, or <code>null</code> to indicate
* that we couldn't obtain a shortcut FactoryBean instance
*/
private FactoryBean getSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
synchronized (getSingletonMutex()) {
BeanWrapper bw = (BeanWrapper) this.factoryBeanInstanceCache.get(beanName);
if (bw != null) {
return (FactoryBean) bw.getWrappedInstance();
}
if (isSingletonCurrentlyInCreation(beanName)) {
return null;
}
Object instance = null;
try {
// Mark this bean as currently in creation, even if just partially.
beforeSingletonCreation(beanName);
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Class beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Object bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
if (bean != null) {
instance = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
if (instance == null) {
bw = createBeanInstance(beanName, mbd, null);
instance = bw.getWrappedInstance();
}
}
finally {
// Finished partial creation of this bean.
afterSingletonCreation(beanName);
}
if (!(instance instanceof FactoryBean)) {
throw new BeanCreationException(beanName,
"Bean instance of type [" + instance.getClass() + "] is not a FactoryBean");
}
if (bw != null) {
this.factoryBeanInstanceCache.put(beanName, bw);
}
return (FactoryBean) instance;
}
}
/**
* Obtain a "shortcut" non-singleton FactoryBean instance to use for a
* <code>getObjectType()</code> call, without full initialization
* of the FactoryBean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the FactoryBean instance, or <code>null</code> to indicate
* that we couldn't obtain a shortcut FactoryBean instance
*/
private FactoryBean getNonSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
if (isPrototypeCurrentlyInCreation(beanName)) {
return null;
}
Object instance = null;
try {
// Mark this bean as currently in creation, even if just partially.
beforePrototypeCreation(beanName);
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Class beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Object bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
if (bean != null) {
instance = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
if (instance == null) {
BeanWrapper bw = createBeanInstance(beanName, mbd, null);
instance = bw.getWrappedInstance();
}
}
finally {
// Finished partial creation of this bean.
afterPrototypeCreation(beanName);
}
if (!(instance instanceof FactoryBean)) {
throw new BeanCreationException(beanName,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -