📄 abstractautowirecapablebeanfactory.java
字号:
if (mergedBeanDefinition.getDependsOn() != null) {
for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {
// Guarantee initialization of beans that the current one depends on.
getBean(mergedBeanDefinition.getDependsOn()[i]);
}
}
BeanWrapper instanceWrapper = null;
Object bean = null;
Object originalBean = null;
String errorMessage = null;
boolean eagerlyCached = false;
try {
// Instantiate the bean.
errorMessage = "Instantiation of bean failed";
if (mergedBeanDefinition.getFactoryMethodName() != null) {
instanceWrapper = instantiateUsingFactoryMethod(beanName, mergedBeanDefinition, args);
}
else if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mergedBeanDefinition.hasConstructorArgumentValues() ) {
instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
}
else {
// No special handling: simply use no-arg constructor.
Object beanInstance = this.instantiationStrategy.instantiate(mergedBeanDefinition, beanName, this);
instanceWrapper = createBeanWrapper(beanInstance);
initBeanWrapper(instanceWrapper);
}
bean = instanceWrapper.getWrappedInstance();
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
if (allowEagerCaching && mergedBeanDefinition.isSingleton()) {
addSingleton(beanName, bean);
eagerlyCached = true;
}
// Initialize the bean instance.
errorMessage = "Initialization of bean failed";
populateBean(beanName, mergedBeanDefinition, instanceWrapper);
if (bean instanceof BeanNameAware) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking setBeanName on BeanNameAware bean '" + beanName + "'");
}
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanFactoryAware) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking setBeanFactory on BeanFactoryAware bean '" + beanName + "'");
}
((BeanFactoryAware) bean).setBeanFactory(this);
}
originalBean = bean;
bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName, mergedBeanDefinition);
invokeInitMethods(beanName, bean, mergedBeanDefinition);
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName, mergedBeanDefinition);
}
catch (BeanCreationException ex) {
if (eagerlyCached) {
removeSingleton(beanName);
}
throw ex;
}
catch (Throwable ex) {
if (eagerlyCached) {
removeSingleton(beanName);
}
throw new BeanCreationException(
mergedBeanDefinition.getResourceDescription(), beanName, errorMessage, ex);
}
// Register bean as disposable, and also as dependent on specified "dependsOn" beans.
registerDisposableBeanIfNecessary(beanName, originalBean, mergedBeanDefinition);
return bean;
}
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* mergedBeanDefinition parameter specifies a class, rather than a factoryBean, or
* an instance variable on a factory object itself configured using Dependency Injection.
* <p>Implementation requires iterating over the static or instance methods with the
* name specified in the RootBeanDefinition (the method may be overloaded) and trying
* to match with the parameters. We don't have the types attached to constructor args,
* so trial and error is the only way to go here. The args array may contain argument
* values passed in programmatically via the overloaded getBean() method.
*/
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mergedBeanDefinition, Object[] args) throws BeansException {
ConstructorArgumentValues cargs = mergedBeanDefinition.getConstructorArgumentValues();
ConstructorArgumentValues resolvedValues = new ConstructorArgumentValues();
int expectedArgCount = 0;
// We don't have arguments passed in programmatically, so we need to resolve the
// arguments specified in the constructor arguments held in the bean definition.
if (args == null) {
expectedArgCount = cargs.getArgumentCount();
resolveConstructorArguments(beanName, mergedBeanDefinition, cargs, resolvedValues);
}
else {
// If we have constructor args, don't need to resolve them.
expectedArgCount = args.length;
}
BeanWrapper bw = createBeanWrapper(null);
initBeanWrapper(bw);
boolean isStatic = true;
Class factoryClass = null;
Object factoryBean = null;
if (mergedBeanDefinition.getFactoryBeanName() != null) {
factoryBean = getBean(mergedBeanDefinition.getFactoryBeanName());
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// It's a static factory method on the bean class.
factoryClass = mergedBeanDefinition.getBeanClass();
}
// Try all methods with this name to see if they match constructor arguments.
for (int i = 0; i < factoryClass.getMethods().length; i++) {
Method factoryMethod = factoryClass.getMethods()[i];
if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic &&
factoryMethod.getName().equals(mergedBeanDefinition.getFactoryMethodName()) &&
factoryMethod.getParameterTypes().length == expectedArgCount) {
Class[] argTypes = factoryMethod.getParameterTypes();
try {
// try to create the required arguments
if (args == null) {
args = createArgumentArray(beanName, mergedBeanDefinition, resolvedValues, bw, argTypes);
}
}
catch (Exception ex) {
// If we failed to match this method, swallow the exception and keep trying new overloaded
// factory methods...
continue;
}
// If we get here, we found a factory method.
Object beanInstance =
this.instantiationStrategy.instantiate(
mergedBeanDefinition, beanName, this, factoryBean, factoryMethod, args);
// TODO: If we got to here, we could cache the resolved Method in the RootBeanDefinition
// for efficiency on future creation, but that would need to be synchronized.
bw.setWrappedInstance(beanInstance);
if (logger.isDebugEnabled()) {
logger.debug("Bean '" + beanName + "' instantiated via factory method '" + factoryMethod + "'");
}
return bw;
}
} // for each method
// If we get here, we didn't match any method.
throw new BeanDefinitionStoreException(
"Cannot find matching factory method '" + mergedBeanDefinition.getFactoryMethodName() +
"' on class [" + factoryClass.getName() + "]");
}
/**
* "autowire constructor" (with constructor arguments by type) behavior.
* Also applied if explicit constructor argument values are specified,
* matching all remaining arguments with beans from the bean factory.
* <p>This corresponds to constructor injection: In this mode, a Spring
* bean factory is able to host components that expect constructor-based
* dependency resolution.
* @param beanName name of the bean to autowire by type
* @param mergedBeanDefinition bean definition to update through autowiring
* @return BeanWrapper for the new instance
*/
protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mergedBeanDefinition)
throws BeansException {
ConstructorArgumentValues cargs = mergedBeanDefinition.getConstructorArgumentValues();
ConstructorArgumentValues resolvedValues = new ConstructorArgumentValues();
BeanWrapper bw = createBeanWrapper(null);
initBeanWrapper(bw);
int minNrOfArgs = 0;
if (cargs != null) {
minNrOfArgs = resolveConstructorArguments(beanName, mergedBeanDefinition, cargs, resolvedValues);
}
Constructor[] constructors = mergedBeanDefinition.getBeanClass().getDeclaredConstructors();
AutowireUtils.sortConstructors(constructors);
Constructor constructorToUse = null;
Object[] argsToUse = null;
int minTypeDiffWeight = Integer.MAX_VALUE;
for (int i = 0; i < constructors.length; i++) {
try {
Constructor constructor = constructors[i];
if (constructor.getParameterTypes().length < minNrOfArgs) {
throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
minNrOfArgs + " constructor arguments specified but no matching constructor found in bean '" +
beanName + "' (hint: specify index arguments for simple parameters to avoid type ambiguities)");
}
if (constructorToUse != null &&
constructorToUse.getParameterTypes().length > constructor.getParameterTypes().length) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
Class[] argTypes = constructor.getParameterTypes();
Object[] args = createArgumentArray(beanName, mergedBeanDefinition, resolvedValues, bw, argTypes);
int typeDiffWeight = AutowireUtils.getTypeDifferenceWeight(argTypes, args);
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = constructor;
argsToUse = args;
minTypeDiffWeight = typeDiffWeight;
}
}
catch (BeansException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring constructor [" + constructors[i] + "] of bean '" + beanName +
"': could not satisfy dependencies", ex);
}
if (i == constructors.length - 1 && constructorToUse == null) {
// all constructors tried
throw ex;
}
else {
// swallow and try next constructor
}
}
}
if (constructorToUse == null) {
throw new BeanCreationException(
mergedBeanDefinition.getResourceDescription(), beanName, "Could not resolve matching constructor");
}
Object beanInstance = this.instantiationStrategy.instantiate(
mergedBeanDefinition, beanName, this, constructorToUse, argsToUse);
bw.setWrappedInstance(beanInstance);
if (logger.isDebugEnabled()) {
logger.debug("Bean '" + beanName + "' instantiated via constructor [" + constructorToUse + "]");
}
return bw;
}
/**
* Resolve the constructor arguments for this bean into the resolvedValues object.
* This may involve looking up other beans.
* This method is also used for handling invocations of static factory methods.
*/
private int resolveConstructorArguments(
String beanName, RootBeanDefinition mergedBeanDefinition,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
int minNrOfArgs;
minNrOfArgs = cargs.getArgumentCount();
for (Iterator it = cargs.getIndexedArgumentValues().entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
int index = ((Integer) entry.getKey()).intValue();
if (index < 0) {
throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
"Invalid constructor argument index: " + index);
}
if (index > minNrOfArgs) {
minNrOfArgs = index + 1;
}
String argName = "constructor argument with index " + index;
ConstructorArgumentValues.ValueHolder valueHolder =
(ConstructorArgumentValues.ValueHolder) entry.getValue();
Object resolvedValue =
resolveValueIfNecessary(beanName, mergedBeanDefinition, argName, valueHolder.getValue());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -