在上一篇Spring源码十五:Bean的加载 中我们通过前面的案例方法,找到了Spring真正开始创建Bean的入口,也就是doGetBean方法。该方法是Spring框架中Bean创建与获取的核心逻辑,实现了复杂的Bean生命周期管理。通过单例缓存、合并Bean定义、处理依赖关系以及类型转换等步骤,确保了Bean实例的正确创建与获取。此流程通过细致的检查与处理,避免了循环依赖,并支持多种作用域的Bean管理,为应用提供了灵活且可靠的Bean管理机制。上一篇,我们只是从整体上看了该方法。
今天开始正式进入该方法的详解,接下来让我看它的第一个方法:
transformedBeanName
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//!!!!!!!!!!!! 这里 这里 今天看这里 !!!!!!!!!!!//
// 获取转换后的Bean名称
final String beanName = transformedBeanName(name);
//!!!!!!!!!!!! 这里 这里 今天看这里 !!!!!!!!!!!//
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 检查单例缓存中是否有手动注册的单例Bean
Object sharedInstance = getSingleton(beanName);
// 如果单缓存中存在则直接从缓存中获取,
// 如果不存在就走else分支,进行实例化
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 获取Bean的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前bean还未被实例化,则在这个判断中准备实例化
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 如果bean的类型是prototype且正在创建,直接抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 检查Bean定义是否存在于当前工厂
/// 获取容器的父容器
BeanFactory parentBeanFactory = getParentBeanFactory();
// 存在父容器,且当前容器没有beanName的BeanDefinition,则通过父容器获取bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
// 标记bean已经开始创建,其实就是将当前beanName 放入alreadyCreated容器中
markBeanAsCreated(beanName);
}
// 进入实例化bean阶段
try {
// 合并容器中beanName对应的BeanDefinition,得到新的root类型BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 校验合并后的rootBeanDefinition是否达到实例化标准,abstractFlag默认是false,如果是true则抛出异常
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 获取当前beanName所依赖的BeanNames数组
String[] dependsOn = mbd.getDependsOn();
// 如果依赖的bean不为空,则注册这些bean且递归调用getBean,提前实例化需要依赖的Bean
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖的bean
registerDependentBean(dep, beanName);
try {
// 递归调用getBean,需要依赖的Bean先实例化
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 判断beanDefinition是单例?
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//是单例:则开始创建单例bean的实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
// 获取bean实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是原型bean
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 实例化前置准备工作
beforePrototypeCreation(beanName);
// 开始实例化
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 实例化以后的处理工作
afterPrototypeCreation(beanName);
}
// 获取原型bean实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 其他bean类型处理
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
// 空抛出异常
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 处理流程类似原型
Object scopedInstance = scope.get(beanName, () -> {
// 创建其他类型作用域bean的前置准备工作
beforePrototypeCreation(beanName);
try {
// 创建其他类型作用域bean
return createBean(beanName, mbd, args);
}
finally {
// 后置处理作用
afterPrototypeCreation(beanName);
}
});
// 获取其他作用域类型实例化对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
// 如果requiredType,且bean类型与入参要求不一致,则需要惊喜转换
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 将BeanDefinition转化成指定类型的bean
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
看到上述代码我们方法,在调用canonicalName的时候,是通过BeanFactroyUtils的transformerBeanName方法先进行了处理,然后再作为canonicalName的参数进行命名的规范。直接进入方法查看:
/**
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
*
* 去掉 Bean 名称中的所有 & 前缀,并返回实际的 Bean 名称。
*
* @param name the name of the bean
* @return the transformed name
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// bean的名称不是以&为前缀的,不处理直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { // String FACTORY_BEAN_PREFIX = "&";
return name;
}
// 如果name以一个或多个符号“&”为前缀,
// 则遍历剔除掉name前缀中所有的“&”,返回name。
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
在这段代码中:
FACTORY_PREFIX
常量表示工厂引用前缀(&
)。getActualBeanName
方法接收一个 Bean 名称作为输入,并去除所有的工厂前缀。while
循环检查 Bean 名称是否以工厂前缀开头。如果是,则使用substring
方法去除前缀,并继续循环直到去除所有前缀。
这个方法会去掉 Bean 名称中的所有 &
前缀,并返回实际的 Bean 名称。至于为什么这么做如果看过详细看过Bean生命周期代码的小伙伴应该知道,咱们先不解读,整个bean相关分析结束就知道啦。那咱们接着往下看:
canonicalName
在 Spring 框架中,bean 的别名(alias)是一种灵活的机制,它允许开发者为一个 bean 定义多个名称。在实际使用中,用户可能通过别名访问某个 bean,因此需要一个过程将别名解析为实际名称,这样 Spring 才能找到对应的 BeanDefinition
。
-
别名注册:
- 在
BeanDefinition
注册到 Spring 容器时,可以为一个 bean 定义多个别名。 - 这些别名与实际名称的映射关系存储在
aliasMap
中。
- 在
-
别名解析:
- 当用户调用
getBean
方法时,传入的名称可能是别名。 canonicalName
方法通过查找aliasMap
,将别名解析为实际名称。- 解析完成后,Spring 使用实际名称查找并实例化对应的
BeanDefinition
。
- 当用户调用
小结
初步分析了bean的名称解析并转换相关的代码逻辑,从下一篇开始,我们就要开始bean加载的核心逻辑分析了。