📄 abstractautowirecapablebeanfactory.java
字号:
resolvedValues.addIndexedArgumentValue(index, resolvedValue, valueHolder.getType());
}
for (Iterator it = cargs.getGenericArgumentValues().iterator(); it.hasNext();) {
ConstructorArgumentValues.ValueHolder valueHolder =
(ConstructorArgumentValues.ValueHolder) it.next();
String argName = "constructor argument";
Object resolvedValue =
resolveValueIfNecessary(beanName, mergedBeanDefinition, argName, valueHolder.getValue());
resolvedValues.addGenericArgumentValue(resolvedValue, valueHolder.getType());
}
return minNrOfArgs;
}
/**
* Create an array of arguments to invoke a Constructor or static factory method,
* given the resolved constructor arguments values.
*/
private Object[] createArgumentArray(
String beanName, RootBeanDefinition mergedBeanDefinition,
ConstructorArgumentValues resolvedValues, BeanWrapper bw, Class[] argTypes)
throws UnsatisfiedDependencyException {
Object[] args = new Object[argTypes.length];
Set usedValueHolders = new HashSet(argTypes.length);
for (int j = 0; j < argTypes.length; j++) {
ConstructorArgumentValues.ValueHolder valueHolder = resolvedValues.getArgumentValue(j, argTypes[j]);
if (valueHolder != null && !usedValueHolders.contains(valueHolder)) {
// Do not consider the same value definition multiple times!
usedValueHolders.add(valueHolder);
if (bw instanceof BeanWrapperImpl) {
// Synchronize if custom editors are registered.
// Necessary because PropertyEditors are not thread-safe.
if (!getCustomEditors().isEmpty()) {
synchronized (getCustomEditors()) {
args[j] = ((BeanWrapperImpl) bw).doTypeConversionIfNecessary(valueHolder.getValue(), argTypes[j]);
}
}
else {
args[j] = ((BeanWrapperImpl) bw).doTypeConversionIfNecessary(valueHolder.getValue(), argTypes[j]);
}
}
else {
// Fallback: a BeanWrapper that oes not support type conversion
// for given values (currently BeanWrapperImpl is needed for this).
if (argTypes[j].isInstance(valueHolder.getValue())) {
args[j] = valueHolder.getValue();
}
else {
throw new UnsatisfiedDependencyException(
mergedBeanDefinition.getResourceDescription(), beanName, j, argTypes[j],
"Could not convert constructor argument value [" + valueHolder.getValue() +
"] to required type [" + argTypes[j].getName() + "] because BeanWrapper [" + bw +
"] does not support type conversion for given values (BeanWrapperImpl needed)");
}
}
}
else {
if (mergedBeanDefinition.getResolvedAutowireMode() != RootBeanDefinition.AUTOWIRE_CONSTRUCTOR) {
throw new UnsatisfiedDependencyException(
mergedBeanDefinition.getResourceDescription(), beanName, j, argTypes[j],
"Did you specify the correct bean references as generic constructor arguments?");
}
Map matchingBeans = findMatchingBeans(argTypes[j]);
if (matchingBeans == null || matchingBeans.size() != 1) {
int matchingBeansCount = (matchingBeans != null ? matchingBeans.size() : 0);
throw new UnsatisfiedDependencyException(
mergedBeanDefinition.getResourceDescription(), beanName, j, argTypes[j],
"There are " + matchingBeansCount + " beans of type [" + argTypes[j] +
"] for autowiring constructor. There should have been 1 to be able to " +
"autowire constructor of bean '" + beanName + "'.");
}
String autowiredBeanName = (String) matchingBeans.keySet().iterator().next();
Object autowiredBean = matchingBeans.values().iterator().next();
args[j] = autowiredBean;
if (mergedBeanDefinition.isSingleton()) {
registerDependentBean(autowiredBeanName, beanName);
}
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via constructor to bean named '" + autowiredBeanName + "'");
}
}
}
return args;
}
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName name of the bean
* @param mergedBeanDefinition the bean definition for the bean
* @param bw BeanWrapper with bean instance
*/
protected void populateBean(String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw)
throws BeansException {
PropertyValues pvs = mergedBeanDefinition.getPropertyValues();
if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues mpvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mergedBeanDefinition, bw, mpvs);
}
// Add property values based on autowire by type if applicable.
if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mergedBeanDefinition, bw, mpvs);
}
pvs = mpvs;
}
dependencyCheck(beanName, mergedBeanDefinition, bw, pvs);
applyPropertyValues(beanName, mergedBeanDefinition, bw, pvs);
}
/**
* Fills in any missing property values with references to
* other beans in this factory if autowire is set to "byName".
* @param beanName name of the bean we're wiring up.
* Useful for debugging messages; not used functionally.
* @param mergedBeanDefinition bean definition to update through autowiring
* @param bw BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByName(
String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw, MutablePropertyValues pvs)
throws BeansException {
String[] propertyNames = unsatisfiedObjectProperties(mergedBeanDefinition, bw);
for (int i = 0; i < propertyNames.length; i++) {
String propertyName = propertyNames[i];
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.addPropertyValue(propertyName, bean);
if (mergedBeanDefinition.isSingleton()) {
registerDependentBean(propertyName, beanName);
}
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
/**
* Abstract method defining "autowire by type" (bean properties by type) behavior.
* <p>This is like PicoContainer default, in which there must be exactly one bean
* of the property type in the bean factory. This makes bean factories simple to
* configure for small namespaces, but doesn't work as well as standard Spring
* behavior for bigger applications.
* @param beanName name of the bean to autowire by type
* @param mergedBeanDefinition bean definition to update through autowiring
* @param bw BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByType(
String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw, MutablePropertyValues pvs)
throws BeansException {
String[] propertyNames = unsatisfiedObjectProperties(mergedBeanDefinition, bw);
for (int i = 0; i < propertyNames.length; i++) {
String propertyName = propertyNames[i];
// look for a matching type
Class requiredType = bw.getPropertyDescriptor(propertyName).getPropertyType();
Map matchingBeans = findMatchingBeans(requiredType);
if (matchingBeans != null && matchingBeans.size() == 1) {
String autowiredBeanName = (String) matchingBeans.keySet().iterator().next();
Object autowiredBean = matchingBeans.values().iterator().next();
pvs.addPropertyValue(propertyName, autowiredBean);
if (mergedBeanDefinition.isSingleton()) {
registerDependentBean(autowiredBeanName, beanName);
}
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
else if (matchingBeans != null && matchingBeans.size() > 1) {
throw new UnsatisfiedDependencyException(
mergedBeanDefinition.getResourceDescription(), beanName, propertyName,
"There are " + matchingBeans.size() + " beans of type [" + requiredType +
"] for autowire by type. There should have been 1 to be able to autowire property '" +
propertyName + "' of bean '" + beanName + "'.");
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by type: no matching bean found");
}
}
}
}
/**
* Return an array of object-type property names that are unsatisfied.
* These are probably unsatisfied references to other beans in the
* factory. Does not include simple properties like primitives or Strings.
* @param mergedBeanDefinition the bean definition the bean was created with
* @param bw the BeanWrapper the bean was created with
* @return an array of object-type property names that are unsatisfied
* @see org.springframework.beans.BeanUtils#isSimpleProperty
*/
protected String[] unsatisfiedObjectProperties(RootBeanDefinition mergedBeanDefinition, BeanWrapper bw) {
Set result = new TreeSet();
PropertyValues pvs = mergedBeanDefinition.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
Set ignoreTypes = getIgnoredDependencyTypes();
for (int i = 0; i < pds.length; i++) {
if (pds[i].getWriteMethod() != null &&
!ignoreTypes.contains(pds[i].getPropertyType()) &&
!pvs.contains(pds[i].getName()) &&
!BeanUtils.isSimpleProperty(pds[i].getPropertyType())) {
result.add(pds[i].getName());
}
}
return (String[]) result.toArray(new String[result.size()]);
}
/**
* Perform a dependency check that all properties exposed have been set,
* if desired. Dependency checks can be objects (collaborating beans),
* simple (primitives and String), or all (both).
* @param beanName the name of the bean
* @param mergedBeanDefinition the bean definition the bean was created with
* @param bw the BeanWrapper the bean was created with
* @param pvs the property values to be applied to the bean
*/
protected void dependencyCheck(
String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw, PropertyValues pvs)
throws UnsatisfiedDependencyException {
int dependencyCheck = mergedBeanDefinition.getDependencyCheck();
if (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_NONE) {
return;
}
Set ignoreTypes = getIgnoredDependencyTypes();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {
if (pds[i].getWriteMethod() != null &&
!ignoreTypes.contains(pds[i].getPropertyType()) &&
!pvs.contains(pds[i].getName())) {
boolean isSimple = BeanUtils.isSimpleProperty(pds[i].getPropertyType());
boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
(isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
(!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
if (unsatisfied) {
throw new UnsatisfiedDependencyException(
mergedBeanDefinition.getResourceDescription(), beanName, pds[i].getName(),
"Set this property value or disable dependency checking for this bean.");
}
}
}
}
/**
* Apply the given property values, resolving any runtime references
* to other beans in this bean factory. Must use deep copy, so we
* don't permanently modify this property.
* @param beanName bean name passed for better exception information
* @param bw BeanWrapper wrapping the target object
* @param pvs new property values
*/
private void applyPropertyValues(
String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw, PropertyValues pvs)
throws BeansException {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -