📄 abstractautowirecapablebeanfactory.java
字号:
if (pvs == null) {
return;
}
// Create a deep copy, resolving any references for values.
MutablePropertyValues deepCopy = new MutablePropertyValues();
PropertyValue[] pvArray = pvs.getPropertyValues();
for (int i = 0; i < pvArray.length; i++) {
PropertyValue pv = pvArray[i];
Object resolvedValue =
resolveValueIfNecessary(beanName, mergedBeanDefinition, pv.getName(), pv.getValue());
deepCopy.addPropertyValue(pvArray[i].getName(), resolvedValue);
}
// Set our (possibly massaged) deep copy.
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 value to see whether it requires a runtime reference
// to another bean to be resolved.
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)", bd);
}
else if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(beanName, mergedBeanDefinition, argName, ref);
}
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
return resolveManagedList(beanName, mergedBeanDefinition, argName, (List) value);
}
else if (value instanceof ManagedSet) {
// May need to resolve contained runtime references.
return resolveManagedSet(beanName, mergedBeanDefinition, argName, (Set) value);
}
else if (value instanceof ManagedMap) {
// May need to resolve contained runtime references.
return resolveManagedMap(beanName, mergedBeanDefinition, argName, (Map) value);
}
else {
// no need to resolve value
return value;
}
}
/**
* Resolve an inner bean definition.
*/
private Object resolveInnerBeanDefinition(String beanName, String innerBeanName, BeanDefinition innerBd)
throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Resolving inner bean definition '" + innerBeanName + "' of bean '" + beanName + "'");
}
RootBeanDefinition mergedInnerBd = getMergedBeanDefinition(innerBeanName, innerBd);
Object innerBean = createBean(innerBeanName, mergedInnerBd, null, false);
if (mergedInnerBd.isSingleton()) {
registerDependentBean(innerBeanName, beanName);
}
return getObjectForSharedInstance(innerBeanName, innerBean);
}
/**
* Resolve a reference to another bean in the factory.
*/
private Object resolveReference(
String beanName, RootBeanDefinition mergedBeanDefinition, String argName, RuntimeBeanReference ref)
throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Resolving reference from property '" + argName + "' in bean '" +
beanName + "' to bean '" + ref.getBeanName() + "'");
}
try {
if (ref.isToParent()) {
if (getParentBeanFactory() == null) {
throw new BeanCreationException(
mergedBeanDefinition.getResourceDescription(), beanName,
"Can't resolve reference to bean '" + ref.getBeanName() +
"' in parent factory: no parent factory available");
}
return getParentBeanFactory().getBean(ref.getBeanName());
}
else {
if (mergedBeanDefinition.isSingleton()) {
registerDependentBean(ref.getBeanName(), beanName);
}
return getBean(ref.getBeanName());
}
}
catch (BeansException ex) {
throw new BeanCreationException(
mergedBeanDefinition.getResourceDescription(), beanName,
"Can't resolve reference to bean '" + ref.getBeanName() +
"' while setting property '" + argName + "'", ex);
}
}
/**
* For each element in the ManagedList, resolve reference if necessary.
*/
private List resolveManagedList(
String beanName, RootBeanDefinition mergedBeanDefinition, String argName, List ml)
throws BeansException {
List resolved = new ArrayList(ml.size());
for (int i = 0; i < ml.size(); i++) {
resolved.add(
resolveValueIfNecessary(
beanName, mergedBeanDefinition,
argName + BeanWrapper.PROPERTY_KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
}
return resolved;
}
/**
* For each element in the ManagedList, resolve reference if necessary.
*/
private Set resolveManagedSet(
String beanName, RootBeanDefinition mergedBeanDefinition, String argName, Set ms)
throws BeansException {
Set resolved = CollectionFactory.createLinkedSetIfPossible(ms.size());
int i = 0;
for (Iterator it = ms.iterator(); it.hasNext();) {
resolved.add(
resolveValueIfNecessary(
beanName, mergedBeanDefinition,
argName + BeanWrapper.PROPERTY_KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
it.next()));
i++;
}
return resolved;
}
/**
* For each element in the ManagedMap, resolve reference if necessary.
*/
private Map resolveManagedMap(
String beanName, RootBeanDefinition mergedBeanDefinition, String argName, Map mm)
throws BeansException {
Map resolved = CollectionFactory.createLinkedMapIfPossible(mm.size());
Iterator it = mm.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
resolved.put(
entry.getKey(),
resolveValueIfNecessary(
beanName, mergedBeanDefinition,
argName + BeanWrapper.PROPERTY_KEY_PREFIX + entry.getKey() + BeanWrapper.PROPERTY_KEY_SUFFIX,
entry.getValue()));
}
return resolved;
}
/**
* Give a bean a chance to react now all its properties are set,
* and a chance to know about its owning bean factory (this object).
* This means checking whether the bean implements InitializingBean or defines
* a custom init method, and invoking the necessary callback(s) if it does.
* <p>To be called by createBean implementations of concrete subclasses.
* @param beanName the bean has in the factory. Used for debug output.
* @param bean new bean instance we may need to initialize
* @param mergedBeanDefinition the bean definition that the bean was created with
* (can also be null, if initializing )
* @throws Throwable if thrown by init methods or by the invocation process
* @see #invokeCustomInitMethod
* @see #createBean
*/
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mergedBeanDefinition)
throws Throwable {
if (bean instanceof InitializingBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with beanName '" + beanName + "'");
}
((InitializingBean) bean).afterPropertiesSet();
}
if (mergedBeanDefinition != null && mergedBeanDefinition.getInitMethodName() != null) {
invokeCustomInitMethod(beanName, bean, mergedBeanDefinition.getInitMethodName());
}
}
/**
* Invoke the specified custom init method on the given bean.
* Called by invokeInitMethods.
* <p>Can be overridden in subclasses for custom resolution of init
* methods with arguments.
* @param beanName the bean has in the factory. Used for debug output.
* @param bean new bean instance we may need to initialize
* @param initMethodName the name of the custom init method
* @see #invokeInitMethods
*/
protected void invokeCustomInitMethod(String beanName, Object bean, String initMethodName)
throws Throwable {
if (logger.isDebugEnabled()) {
logger.debug("Invoking custom init method '" + initMethodName +
"' on bean with beanName '" + beanName + "'");
}
try {
Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);
if (initMethod == null) {
throw new NoSuchMethodException("Couldn't find an init method named '" + initMethodName +
"' on bean with name '" + beanName + "'");
}
if (!Modifier.isPublic(initMethod.getModifiers())) {
initMethod.setAccessible(true);
}
initMethod.invoke(bean, (Object[]) null);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
//---------------------------------------------------------------------
// Abstract method to be implemented by concrete subclasses
//---------------------------------------------------------------------
/**
* Find bean instances that match the required type. Called by autowiring.
* If a subclass cannot obtain information about bean names by type,
* a corresponding exception should be thrown.
* @param requiredType the type of the beans to look up
* @return a Map of bean names and bean instances that match the required type,
* or null if none found
* @throws BeansException in case of errors
* @see #autowireByType
* @see #autowireConstructor
*/
protected abstract Map findMatchingBeans(Class requiredType) throws BeansException;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -