📄 abstractautowirecapablebeanfactory.java
字号:
superClass = null;
}
}
}
}
return result;
}
/**
* 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 it's applied
if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mergedBeanDefinition, bw, mpvs);
}
// add property values based on autowire by type if it's applied
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 '" +
matchingBeans.keySet().iterator().next() + "'");
}
}
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");
}
}
}
}
/**
* 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 name of 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.getPropertyValue(pds[i].getName()) == null) {
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.");
}
}
}
}
/**
* 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.
* @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();
Set ignoreTypes = getIgnoredDependencyTypes();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {
String name = pds[i].getName();
if (pds[i].getWriteMethod() != null &&
!BeanUtils.isSimpleProperty(pds[i].getPropertyType()) &&
!ignoreTypes.contains(pds[i].getPropertyType()) &&
mergedBeanDefinition.getPropertyValues().getPropertyValue(name) == null) {
result.add(name);
}
}
return (String[]) result.toArray(new String[result.size()]);
}
/**
* 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
*/
protected void applyPropertyValues(
String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw, PropertyValues pvs)
throws BeansException {
if (pvs == null) {
return;
}
MutablePropertyValues deepCopy = new MutablePropertyValues(pvs);
PropertyValue[] pvals = deepCopy.getPropertyValues();
for (int i = 0; i < pvals.length; i++) {
Object value = resolveValueIfNecessary(
beanName, mergedBeanDefinition, pvals[i].getName(), pvals[i].getValue());
PropertyValue pv = new PropertyValue(pvals[i].getName(), value);
// update mutable copy
deepCopy.setPropertyValueAt(pv, i);
}
// set our (possibly massaged) deepCopy
try {
// synchronize if custom editors are registered
// necessary because PropertyEditors are not thread-safe
if (!getCustomEditors().isEmpty()) {
synchronized (this) {
bw.setPropertyValues(deepCopy);
}
}
else {
bw.setPropertyValues(deepCopy);
}
}
catch (BeansException ex) {
// improve the message by showing the context
throw new BeanCreationException(
mergedBeanDefinition.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
/**
* Given a PropertyValue, return a value, resolving any references to other
* beans in the factory if necessary. The value could be:
* <li>A BeanDefinition, which leads to the creation of a corresponding
* new bean instance. Singleton flags and names of such "inner beans"
* are always ignored: Inner beans are anonymous prototypes.
* <li>A RuntimeBeanReference, which must be resolved.
* <li>A ManagedList. This is a special collection that may contain
* RuntimeBeanReferences or Collections that will need to be resolved.
* <li>A ManagedSet. May also contain RuntimeBeanReferences or
* Collections that will need to be resolved.
* <li>A ManagedMap. In this case the value may be a RuntimeBeanReference
* or Collection that will need to be resolved.
* <li>An ordinary object or null, in which case it's left alone.
*/
protected Object resolveValueIfNecessary(
String beanName, RootBeanDefinition mergedBeanDefinition, String argName, Object value)
throws BeansException {
// We must check each PropertyValue to see whether it
// requires a runtime reference to another bean to be resolved.
// If it does, we'll attempt to instantiate the bean and set the reference.
if (value instanceof BeanDefinitionHolder) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBeanDefinition(beanName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBeanDefinition(
beanName, "(inner bean of type " + bd.getBeanClass().getName() + ")", bd);
}
else if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(beanName, mergedBeanDefinition, argName, ref);
}
else if (value instanceof ManagedList) {
// Convert from managed list. This is a special container that may
// contain runtime bean references. May need to resolve references.
return resolveManagedList(beanName, mergedBeanDefinition, argName, (List) value);
}
else if (value instanceof ManagedSet) {
// Convert from managed set. This is a special container that may
// contain runtime bean references. May need to resolve references.
return resolveManagedSet(beanName, mergedBeanDefinition, argName, (Set) value);
}
else if (value instanceof ManagedMap) {
// Convert from managed map. This is a special container that may
// contain runtime bean references. May need to resolve references.
return resolveManagedMap(beanName, mergedBeanDefinition, argName, (Map) value);
}
else {
// no need to resolve value
return value;
}
}
/**
* Resolve an inner bean definition.
*/
protected Object resolveInnerBeanDefinition(String beanName, String innerBeanName, BeanDefinition innerBd)
throws BeansException {
RootBeanDefinition mergedInnerBd = getMergedBeanDefinition(innerBeanName, innerBd);
Object innerBean = createBean(innerBeanName, mergedInnerBd, null, false);
if (mergedInnerBd.isSingleton()) {
if (innerBean instanceof DisposableBean) {
registerDependentBean(innerBeanName, beanName);
// keep reference to inner bean, to be able to destroy it on factory shutdown
this.disposableInnerBeans.put(innerBeanName, innerBean);
}
}
return getObjectForSharedInstance(innerBeanName, innerBean);
}
/**
* Resolve a reference to another bean in the factory.
*/
protected Object resolveReference(
String beanName, RootBeanDefinition mergedBeanDefinition, String argName, RuntimeBeanReference ref)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -