📄 abstractbeanfactory.java
字号:
/**
* Return the bean name, stripping out the factory dereference prefix if necessary,
* and resolving aliases to canonical names.
*/
protected String transformedBeanName(String name) {
String beanName = BeanFactoryUtils.transformedBeanName(name);
// Handle aliasing.
synchronized (this.aliasMap) {
String canonicalName = beanName;
String resolvedName = null;
do {
resolvedName = (String) this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
}
/**
* Initialize the given BeanWrapper with the custom editors registered
* with this factory. To be called for BeanWrappers that will create
* and populate bean instances.
* @param bw the BeanWrapper to initialize
*/
protected void initBeanWrapper(BeanWrapper bw) {
for (Iterator it = getCustomEditors().entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Class clazz = (Class) entry.getKey();
PropertyEditor editor = (PropertyEditor) entry.getValue();
bw.registerCustomEditor(clazz, editor);
}
}
/**
* Convert the given value into the specified target type,
* using a default BeanWrapper instance.
* @param value the original value
* @param targetType the target type
* @return the converted value, matching the target type
* @throws org.springframework.beans.TypeMismatchException if type conversion failed
* @see #doTypeConversionIfNecessary(Object, Class, org.springframework.beans.BeanWrapperImpl)
*/
protected Object doTypeConversionIfNecessary(Object value, Class targetType) throws TypeMismatchException {
BeanWrapperImpl bw = new BeanWrapperImpl();
initBeanWrapper(bw);
return doTypeConversionIfNecessary(value, targetType, bw);
}
/**
* Convert the given value into the specified target type,
* using the specified BeanWrapper.
* @param value the original value
* @param targetType the target type
* @param bw the BeanWrapper to work on
* @return the converted value, matching the target type
* @throws org.springframework.beans.TypeMismatchException if type conversion failed
* @see org.springframework.beans.BeanWrapperImpl#doTypeConversionIfNecessary(Object, Class)
*/
protected Object doTypeConversionIfNecessary(Object value, Class targetType, BeanWrapperImpl bw)
throws TypeMismatchException {
// Synchronize if custom editors are registered.
// Necessary because PropertyEditors are not thread-safe.
if (!getCustomEditors().isEmpty()) {
synchronized (getCustomEditors()) {
return bw.doTypeConversionIfNecessary(value, targetType);
}
}
else {
return bw.doTypeConversionIfNecessary(value, targetType);
}
}
/**
* Return a RootBeanDefinition for the given bean name,
* merging a child bean definition with its parent if necessary.
* @param name the name of the bean to retrieve the merged definition for
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @throws BeansException in case of errors
*/
public RootBeanDefinition getMergedBeanDefinition(String name) throws BeansException {
return getMergedBeanDefinition(name, false);
}
/**
* Return a RootBeanDefinition, even by traversing parent if the parameter is a
* child definition. Can ask the parent bean factory if not found in this instance.
* @param name the name of the bean to retrieve the merged definition for
* @param includingAncestors whether to ask the parent bean factory if not found
* in this instance
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedBeanDefinition(String name, boolean includingAncestors)
throws BeansException {
String beanName = transformedBeanName(name);
// Efficiently check whether bean definition exists in this factory.
if (includingAncestors && !containsBeanDefinition(beanName) &&
getParentBeanFactory() instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName, true);
}
// Resolve merged bean definition locally.
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
/**
* Return a RootBeanDefinition for the given top-level bean, by merging with
* the parent if the given bean's definition is a child bean definition.
* @param beanName the name of the bean definition
* @param bd the original bean definition (Root/ChildBeanDefinition)
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
if (bd instanceof RootBeanDefinition) {
// Return root bean definition as-is.
return (RootBeanDefinition) bd;
}
else if (bd instanceof ChildBeanDefinition) {
// Child bean definition: needs to be merged with parent.
ChildBeanDefinition cbd = (ChildBeanDefinition) bd;
RootBeanDefinition pbd = null;
try {
if (!beanName.equals(cbd.getParentName())) {
pbd = getMergedBeanDefinition(cbd.getParentName(), true);
}
else {
if (getParentBeanFactory() instanceof AbstractBeanFactory) {
AbstractBeanFactory parentFactory = (AbstractBeanFactory) getParentBeanFactory();
pbd = parentFactory.getMergedBeanDefinition(cbd.getParentName(), true);
}
else {
throw new NoSuchBeanDefinitionException(cbd.getParentName(),
"Parent name '" + cbd.getParentName() + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(cbd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + cbd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
RootBeanDefinition rbd = new RootBeanDefinition(pbd);
rbd.overrideFrom(cbd);
// Validate merged definition: mainly to prepare method overrides.
try {
rbd.validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(rbd.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
return rbd;
}
else {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Definition is neither a RootBeanDefinition nor a ChildBeanDefinition");
}
}
/**
* Check the given merged bean definition,
* potentially throwing validation exceptions.
* @param mergedBeanDefinition the bean definition to check
* @param beanName the name of the bean
* @param requiredType the required type of the bean
* @param args the arguments for bean creation, if any
* @throws BeansException in case of validation failure
*/
protected void checkMergedBeanDefinition(
RootBeanDefinition mergedBeanDefinition, String beanName, Class requiredType, Object[] args)
throws BeansException {
// check if bean definition is not abstract
if (mergedBeanDefinition.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
// Check if required type can match according to the bean definition.
// This is only possible at this early stage for conventional beans!
if (mergedBeanDefinition.hasBeanClass()) {
Class beanClass = mergedBeanDefinition.getBeanClass();
if (requiredType != null && mergedBeanDefinition.getFactoryMethodName() == null &&
!FactoryBean.class.isAssignableFrom(beanClass) && !requiredType.isAssignableFrom(beanClass)) {
throw new BeanNotOfRequiredTypeException(beanName, requiredType, beanClass);
}
}
// Check validity of the usage of the args parameter. This can
// only be used for prototypes constructed via a factory method.
if (args != null) {
if (mergedBeanDefinition.isSingleton()) {
throw new BeanDefinitionStoreException(
"Cannot specify arguments in the getBean() method when referring to a singleton bean definition");
}
else if (mergedBeanDefinition.getFactoryMethodName() == null) {
throw new BeanDefinitionStoreException(
"Can only specify arguments in the getBean() method in conjunction with a factory method");
}
}
}
/**
* Get the object for the given shared bean, either the bean
* instance itself or its created object in case of a FactoryBean.
* @param name name that may include factory dereference prefix
* @param beanInstance the shared bean instance
* @return the singleton instance of the bean
*/
protected Object getObjectForSharedInstance(String name, Object beanInstance) throws BeansException {
String beanName = transformedBeanName(name);
// Don't let calling code try to dereference the
// bean factory if the bean isn't a factory.
if (isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (beanInstance instanceof FactoryBean) {
if (!isFactoryDereference(name)) {
// Return bean instance from factory.
FactoryBean factory = (FactoryBean) beanInstance;
if (logger.isDebugEnabled()) {
logger.debug("Bean with name '" + beanName + "' is a factory bean");
}
try {
beanInstance = factory.getObject();
}
catch (Exception ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
if (beanInstance == null) {
throw new FactoryBeanNotInitializedException(
beanName, "FactoryBean returned null object: " +
"probably not fully initialized (maybe due to circular bean reference)");
}
}
else {
// The user wants the factory itself.
if (logger.isDebugEnabled()) {
logger.debug("Calling code asked for FactoryBean instance for name '" + beanName + "'");
}
}
}
return beanInstance;
}
/**
* Determine whether the bean with the given name is a FactoryBean.
* @param name the name of the bean to check
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
*/
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name);
synchronized (this.singletonCache) {
Object beanInstance = this.singletonCache.get(beanName);
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
}
}
// No singleton instance found -> check bean definition.
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof AbstractBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((AbstractBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
return (bd.hasBeanClass() && FactoryBean.class.equals(bd.getBeanClass()));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -