深入解析 Spring Bean 规范名称获取:剖析 AbstractBeanFactory 中的 doGetBean
2023-10-26 09:21:57
揭秘 Bean 规范名称获取的奥秘
在 Spring 框架中,Bean 规范名称是一个重要的概念,它代表了 Bean 在 Spring 容器中的唯一标识。Spring 框架提供了多种方式来获取 Bean 的规范名称,而 AbstractBeanFactory 类中的 doGetBean 方法则是其中最常用的一种。
AbstractBeanFactory 中的 doGetBean 方法
doGetBean 方法是 AbstractBeanFactory 类中的一个重要方法,它负责根据 Bean 的名称或别名获取 Bean 的实例。该方法首先会尝试从 Spring 容器中获取 Bean 的实例,如果 Bean 的实例已经存在,则直接返回该实例。如果 Bean 的实例不存在,则 doGetBean 方法会根据 Bean 的定义创建 Bean 的实例并返回。
在 doGetBean 方法中,Spring 框架首先会根据 Bean 的名称或别名获取 Bean 的定义信息。如果 Bean 的定义信息存在,则会根据 Bean 的定义信息创建 Bean 的实例。在创建 Bean 的实例时,Spring 框架会首先获取 Bean 的规范名称。Bean 的规范名称是一个完全限定的类名,它由 Bean 所在的包名和 Bean 的类名组成。
获取 Bean 规范名称的步骤
Spring 框架通过以下步骤获取 Bean 的规范名称:
- 从 Bean 定义信息中获取 Bean 的 BeanNameResolver 对象。BeanNameResolver 对象负责解析 Bean 的名称。
- 调用 BeanNameResolver 对象的 resolve 方法解析 Bean 的名称。
- 将解析后的 Bean 名称与 Bean 的定义信息中的 Bean 类名合并,形成 Bean 的规范名称。
代码示例
public Object doGetBean(final String name, final Class<?> requiredType,
final Object[] args, final boolean typeCheckOnly) throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet. This is a temporary state.");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance.
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if instance was injected previously as a dependency...
BeanFactory parent = getParentBeanFactory();
if (parent != null && !beanName.equals(ORIGINAL_INSTANCE_SUFFIX) &&
isApplicationContext() && parent.containsBean(beanName)) {
sharedInstance = parent.getBean(beanName);
}
if (sharedInstance == null) {
// No instance found - try to create one.
Object beanFactory = getBeanFactory();
if (beanFactory instanceof ConfigurableListableBeanFactory) {
bean = ((ConfigurableListableBeanFactory) beanFactory).resolveDependency(
getRequiredBeanName(name), requiredType, args, typeCheckOnly);
}
else {
bean = resolveDependency(beanName, requiredType, args, typeCheckOnly);
}
}
}
// Handle manually registered singleton that are in creation...
if (bean != null && !typeCheckOnly) {
addSingletonFactory(beanName, () -> getSingleton(beanName));
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (bean instanceof FactoryBean ?
((FactoryBean<?>) bean).getObject() : bean));
}
}
return bean;
}
原理分析
在 doGetBean 方法中,Spring 框架首先会从 Bean 定义信息中获取 Bean 的 BeanNameResolver 对象。BeanNameResolver 对象负责解析 Bean 的名称。Spring 框架提供了多种 BeanNameResolver 的实现,其中最常用的是 DefaultBeanNameResolver 类。DefaultBeanNameResolver 类会将 Bean 的名称直接作为 Bean 的规范名称。
如果 Bean 的定义信息中没有指定 BeanNameResolver 对象,则 Spring 框架会使用默认的 BeanNameResolver 对象 DefaultBeanNameResolver。DefaultBeanNameResolver 类会将 Bean 的名称直接作为 Bean 的规范名称。
Spring 框架通过 BeanNameResolver 对象解析 Bean 的名称后,会将解析后的 Bean 名称与 Bean 的定义信息中的 Bean 类名合并,形成 Bean 的规范名称。Bean 的规范名称是一个完全限定的类名,它由 Bean 所在的包名和 Bean 的类名组成。
总结
Spring 框架通过 doGetBean 方法获取 Bean 的规范名称。Bean 的规范名称是一个完全限定的类名,它由 Bean 所在的包名和 Bean 的类名组成。Spring 框架通过 BeanNameResolver 对象解析 Bean 的名称,然后将解析后的 Bean 名称与 Bean 的定义信息中的 Bean 类名合并,形成 Bean 的规范名称。