相关源码注释
ApplicationContext
Spring 5 DefaultResourceLoader 源码注释
Spring 5 AbstractApplicationContext 源码注释
BeanFactory
Spring 5 SimpleAliasRegistry 源码注释
Spring 5 DefaultSingletonBeanRegistry 源码注释
Spring 5 FactoryBeanRegistrySupport 源码注释
Spring 5 AbstractBeanFactory 源码注释
Spring 5 AbstractAutowireCapableBeanFactory 源码注释
Spring 5 DefaultLisbaleBeanFactory 源码注释
getType(factoryBeanName);
确定具有给定名称的bean类型(为了确定其对象类型,默认让FactoryBean以初始化)。
由 AbstractBeanFactory 实现 。
/**
* 确定具有给定名称的bean类型(为了确定其对象类型,默认让FactoryBean以初始化)。
*
* @param name the name of the bean to query -- 要查询的bean名
* @return Bean的类型;如果不确定,则为null
* @throws NoSuchBeanDefinitionException 如果没有给定名称的bean
* @see #getType(String, boolean)
*/
@Override
@Nullable
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return getType(name, true);
}
getType(name, true);
确定具有给定名称的bean类型。更具体地说,确定getBean将针对给定名称返回的对象 的类型.
逻辑步骤总结:
- 获取name对应的规范名称【全类名】,包括以’&'开头的name。然后将结果赋值给变量beanName
- 获取beanName注册的单例对象,但不会导致单例对象的创建,如果成功获取到且该单例对象 又不是NullBean
- 如果bean的单例对象是FactoryBean的实例 且 name不是FactoryBean的解引用名, 将beanInstance强转为FactoryBean,获取其创建出来的对象的类型并返回
- 否则获取beanInstance的类型并返回
- 获取该工厂的父级bean工厂,成功获取到了且该bean工厂包含具有beanName的bean定义, 就从父级bean工厂中获取name的全类名的bean类型并返回,【递归】
- 获取beanName对应的合并RootBeanDefinition的Bean定义持有者,通过持有者的合并的RootBeanDefinitio获取所对应bean名的 最终bean类型,而这类型不属于FactoryBean类型的话就返回出去。
- 尝试预测beanName的最终bean类型,如果该类型属于FactoryBean类型
- 如果name不是FactoryBean的解引用名,则尽可能的使用beanName和mbd去获取FactoryBean定义的bean类型。
- 如果是FactoryBean的解引用,就直接返回该beanName的最终bean类型
- 如果没有成功预测到beanName的最终bean类型 或者 最终bean类型不属于FactoryBean类型, 再加上如果name不是FactoryBean的解引用名,就直接返回该beanName的最终bean类型,否则返回null
/**
* 确定具有给定名称的bean类型。更具体地说,确定getBean将针对给定名称返回的对象 的类型.
* </p>
* @param name the name of the bean to query -- 要查询的bean名
* @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
* just for the purpose of determining its object type
* -- {@code FactoryBean}是否可以初始化仅仅是为了确定其对象类型
* @return
* @throws NoSuchBeanDefinitionException
*/
@Override
@Nullable
public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
//获取name对应的规范名称【全类名】,包括以'&'开头的name
String beanName = transformedBeanName(name);
// Check manually registered singletons.
// 检查手动注册的单例
// 获取beanName注册的单例对象,但不会创建早期引用
Object beanInstance = getSingleton(beanName, false);
//如果成功获取到beanName的单例对象,且 该单例对象又不是NullBean,NullBean用于表示null
if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
//如果bean的单例对象是FactoryBean的实例 且 name不是FactoryBean的解引用
if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
//将beanInstance强转为FactoryBean,获取其创建出来的对象的类型并返回
return getTypeForFactoryBean((FactoryBean<?>) beanInstance);
}
else {
//获取beanInstance的类型并返回
return beanInstance.getClass();
}
}
// No singleton instance found -> check bean definition.
// 找不到单例实例 -> 检查bean定义
//获取该工厂的父级bean工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果成功获取到了父级bean工厂 且 该bean工厂包含具有beanName的bean定义
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// No bean definition found in this factory -> delegate to parent.
// 在该工厂中找不到bean定义 -> 委托给父对象
// originalBeanName:获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】
// 从父级bean工厂中获取name的全类名的bean类型,【递归】
return parentBeanFactory.getType(originalBeanName(name));
}
//获取beanName对应的合并RootBeanDefinition,如果bean对应于子bean定义,则遍历父bean定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Check decorated bean definition, if any: We assume it'll be easier
// to determine the decorated bean's type than the proxy's type.
// 检查修饰的bean定义(如果有):我们假设确定修饰的bean类型比代理类型更容易
// 获取mbd的Bean定义持有者
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
//如果成功获取到mbd的Bean定义持有者 且 name不是FactoryBean的解引用
// FactoryBean的解引用指的是FactoryBean使用getObject方法得到的对象
if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
//获取合并的RootBeanDefinition
RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
//尝试预测dbd的bean名的最终bean类型
Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
//如果成功预测到了bdd的bean名的最终bean类型 且 targetClass不属于FactoryBean类型
if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
//返回该预测到的dbd的bean名的最终bean类型
return targetClass;
}
}
//尝试预测beanName的最终bean类型
Class<?> beanClass = predictBeanType(beanName, mbd);
// Check bean class whether we're dealing with a FactoryBean.
// 检查bean类是否正在处理FactoryBean
// 如果成功预测到beanName的最终bean类型 且 该类属于FactoryBean类型
if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
//如果name不是FactoryBean的解引用名
if (!BeanFactoryUtils.isFactoryDereference(name)) {
// If it's a FactoryBean, we want to look at what it creates, not at the factory class.
// 如果是FactoryBean,则我们要查看它创建的内容,而不是工厂类
//尽可能的使用beanName和mbd去获取FactoryBean定义的bean类型
return getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();
}
else {
//如果是FactoryBean的解引用,就直接返回该beanName的最终bean类型
return beanClass;
}
}
else {
//如果没有成功预测到beanName的最终bean类型 或者 最终bean类型不属于FactoryBean类型
//如果name不是FactoryBean的解引用名,就直接返回该beanName的最终bean类型,否则返回null
return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
}
}
transformedBeanName(name);
去除name开头的’&‘字符,获取name最终的规范名称【最终别名或者是全类名】:去除开头的’&'字符,返回剩余的字符串得到转换后的Bean名称, 然后通过递归形式在 aliasMap【别名映射到规范名称集合】中得到最终的规范名称
/**
* Return the bean name, stripping out the factory dereference prefix if necessary,
* and resolving aliases to canonical names.
* <p>返回Bean名称,如果必要,去除工厂取消前缀,并将别名解析为规范名称</p>
* @param name the user-specified name - 用户指定的名称
* @return the transformed bean name - 转换后的bena名称
*/
protected String transformedBeanName(String name) {
//去除开头的'&'字符,返回剩余的字符串得到转换后的Bean名称,然后通过递归形式在
// aliasMap【别名映射到规范名称集合】中得到最终的规范名称
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils.transformedBeanName(name)
去除开头的’&'字符,返回剩余的字符串作为转换后的Bean名称【可能是全类名】
- 如果name为null,抛出异常
- 如果name不是以’&'开头,就直接返回
- 从具有FactoryBean前缀的名称缓存到剥离的名称的ConcurrentHashMap【transformedBenaNameCache】 中获取bean名对应的转换后的名称并返回
- 获取不到时就构建一个:从name的开头位置去掉’&’,再重新检查是否还是以’&‘开头,是的话就再截直到没有出现’&'开头为止。所得到 的字符串就是Bean名称【可能是全类名】
/**
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
* <p>返回实际的bean名称,删除工厂取消引用前缀(如果有的话,还删除重复的
* 工厂前缀(如果找到))</p>
* <p>用于获取以'&'开头的name对应的bean名,如果bean不是'&'开头,就直接返回该name</p>
* @param name the name of the bean - bean名
* @return the transformed name - 转换后的名称
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
public static String transformedBeanName(String name) {
//如果bean名为null,抛出异常
Assert.notNull(name, "'name' must not be null");
//如果bean名不是以'&'开头,就直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
//从transformedBenaNameCache中获取bean名对应的转换后的名称
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
//从beanName的开头位置去掉'&',并重新赋值给beanName,再重新检查是还是以'&'开头,是的话就再截
// 知道开头不是以'&'开头后,加入到transformedBeanNameCache中
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
canonicalName(name)
获取name的最终别名或者是全类名。通过递归形式在aliasMap【别名映射到规范名称集合】中得到最终的规范名称
由 SimpleAliasRegistry 实现。
/**
* Map from alias to canonical name.
* <p>从别名映射到规范名称</p>
* <p>整个Map数据结构应该要抽象理解为一个二维数组,因为在检索别名的时候,是可以通过别名查别名的。</p>
* <p>举个栗子:
* <ol>
* <li>A是B的别名,C是B的别名,存放到aliasMap中的数据结构就是:[{key=B,val=A},{key=C,val=B}]</li>
* <li>当要获取A的所有别名[B,C]时:先获取A的Key->B,则通过递归形式获取B的key->C。</li>
* </ol>
* </p>
* */
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
/**
* Determine the raw name, resolving aliases to canonical names.
* <p>确定原始名称,将别名解析为规范名称</p>
* @param name the user-specified name - 用户指定的名称
* @return the transformed name - 转换后的名称
*/
public String canonicalName(String name) {
//规范名称初始化化传入的name
String canonicalName = name;
// Handle aliasing... 处理别名
String resolvedName;
//从下面代码可以看出,aliasMap的存储形式是:
// C是真正的规范名称,A,B都是别名:
// aliasMap={key:A,val:B;key:B,val:C},通过A拿到B,再通过B拿到C
do {
//通过 规范名称 从 aliasMap中获取解析后的名称
resolvedName = this.aliasMap.get(canonicalName);
//如果找到了解析后的名称
if (resolvedName != null) {
//规范名称重新赋值为解析后名称
canonicalName = resolvedName;
}
}
//只要找到了解析后的名称
while (resolvedName != null);
return canonicalName;
}
getSingleton(beanName, false);
获取以beanName注册的(原始)单例对象:
- 从单例对象的高速缓存【singletonObjects】中获取beanName的单例对象,赋值为【singletonObject】
- 如果单例对象没成功获取,并且 baneName 是正在被创建:
- 同步,以singletonObjects作为锁
- 从早期单例对象的高速缓存【earlySingletonObjects】中获取bean对象,赋值为【singletonObject】
- 如果singletonObject为null,且允许创建早期引用:
- 从单例工厂的缓存【singletonFactories】中获取beanName的单例工厂对象,赋值给【singletonFactory】
- 如果singletonFactory不为null:
- 从singletonFactory中获取该beanName的单例对象,作为singletonObject
- 添加beanName和singletonObject到 早期单例对象高速缓存【earlySingletonObjects】中
- 从单例对象工厂缓存【singletonFactories】中移除beanName的单例对象工厂
- 返回singletonObject
/**
* Return the (raw) singleton object registered under the given name.
* <p>返回以给定名称注册的(原始)单例对象,如果单例对象没有找到,并且beanName存在
* 正在创建的Set集合中</p>
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* <p>检查已经实例化的单例,并且还允许对当前的单例的早期引用(解析循环引用)</p>
* @param beanName the name of the bean to look for - 要寻找的bean名
* @param allowEarlyReference whether early references should be created or not
* - 是否应创建早期引用
* @return the registered singleton object, or {@code null} if none found
* - 注册的单例对象;如果找不到,则为{@code null}
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例对象的高速缓存中获取beanName的单例对象
Object singletonObject = this.singletonObjects.get(beanName);
//如果单例对象没有找到,并且 baneName 是正在被创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//同步,以singletonObjects作为锁
synchronized (this.singletonObjects) {
//从早期单例对象的高速缓存中获取bean对象
singletonObject = this.earlySingletonObjects.get(beanName);
//如果获取不了bean的单例对象,且允许创建早期引用
if (singletonObject == null && allowEarlyReference) {
//从单例工厂的缓存中获取beanName的单例工厂对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果beanName的单例工厂对象找到了
if (singletonFactory != null) {
//从beanName的单例工厂对象中获取该beanName的单例对象
singletonObject = singletonFactory.getObject();
//下面的操作主要是为了防止beanName对应的对象重复构建
//添加beanName和其对应的beanName单例对象到 早期单例对象高速缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//从单例对象工厂缓存中移除beanName的单例对象工厂
this.singletonFactories.remove(beanName);
}
}
}
}
//返回beanName对应的单例对象
return singletonObject;
}
BeanFactoryUtils.isFactoryDereference(name)
返回给定名称是否为FactoryBean的解引用.判断依据:name是以’&'开头,就是FactoryBean的解引用
/**
* Return whether the given name is a factory dereference
* (beginning with the factory dereference prefix).
* <p>返回给定名称是否为FactoryBean的解引用名.(从FactoryBean的解引用前缀开始)</p>
* @param name the name of the bean -- bean名
* @return whether the given name is a factory dereference -- 给定名称是否为BeanFactory的解引用
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
public static boolean isFactoryDereference(@Nullable String name) {
//如果有传入bean名且bean名是以'&'开头,则返回true,表示是BeanFactory的解引用,否则
// 返回false,表示不是BeanFactory的解引用
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
getTypeForFactoryBean((FactoryBean<?>) beanInstance)
确定给定FactoryBean的创建出来的对象的类型,将调用factoryBean的getObjectType所得到结果返回出去
/**
* Determine the type for the given FactoryBean.
* <p>确定给定FactoryBean的创建出来的对象的类型,将调用factoryBean的getObjectType所
* 得到结果返回出去</p>
* @param factoryBean the FactoryBean instance to check -- 要检查的FactoryBean实例
* @return the FactoryBean's object type,
* or {@code null} if the type cannot be determined yet
* -- FactoryBean的对象类型;如果尚不能确定类型,则返回null
*/
@Nullable
protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
try {
//如果成功获取到系统的安全管理器
if (System.getSecurityManager() != null) {
//使用特权的方式获取factoryBean的创建对象的类型并返回
return AccessController.doPrivileged((PrivilegedAction<Class<?>>)
factoryBean::getObjectType, getAccessControlContext());
}
else {
//获取factoryBean的创建对象的类型并返回
return factoryBean.getObjectType();
}
}
//捕获所有异常,一般在FactoryBean的getObjectType实现中抛出
catch (Throwable ex) {
// Thrown from the FactoryBean's getObjectType implementation.
// 从FactoryBean的getObjectType实现抛出
// 日志信息:尽管合同上如果尚不能确定其对象的类型,则返回null,当FactoryBean从getObjectType引发了异常。
logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
"that it should return null if the type of its object cannot be determined yet", ex);
return null;
}
}
containsBeanDefinition(beanName)
在 AbstractBeanFactory 中是个抽象方法
/**
* Check if this bean factory contains a bean definition with the given name.
* Does not consider any hierarchy this factory may participate in.
* Invoked by {@code containsBean} when no cached singleton instance is found.
* <p>该BeanFactory是否包含beanName的BeanDefinition对象。不考虑工厂可能参与的任何层次结构。
* 未找到缓存的单例实例时,由{@code containsBena}调用。</p>
* <p>Depending on the nature of the concrete bean factory implementation,
* this operation might be expensive (for example, because of directory lookups
* in external registries). However, for listable bean factories, this usually
* just amounts to a local hash lookup: The operation is therefore part of the
* public interface there. The same implementation can serve for both this
* template method and the public interface method in that case.
* <p>根据具体bean工厂实现的性质,此操作可能很昂贵(例如,由于在外部注册表中进行目录
* 寻找)。但是,对应可列出的bean工厂,这通常只相当于本地哈希查找:因此,该操作是该处
* 工厂接口的一部分。在这种情况下,该模板方法和公共接口方法都可以使用相同的实现。</p>
* @param beanName the name of the bean to look for - 要查找的bean名
* @return if this bean factory contains a bean definition with the given name
* - 如果此bean工厂包含具有给定名称的bean定义。
* @see #containsBean
* @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition
*/
protected abstract boolean containsBeanDefinition(String beanName);
具体由 DefaultListableBeanFactory 实现
/**
* Map of bean definition objects, keyed by bean name.
* <p>Bean定义对象的映射,以Bean名称为键</p>
* */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/**
* 本地工厂中BeanDefinition对象映射【beanDefinitionMap】中是否存在beanName该键名
* @param beanName the name of the bean to look for -- 要寻找的bean名
*/
@Override
public boolean containsBeanDefinition(String beanName) {
//如果beanName为null,抛出异常
Assert.notNull(beanName, "Bean name must not be null");
//从Beand定义对象映射中判断beanName是否存在该键
return this.beanDefinitionMap.containsKey(beanName);
}
getMergedLocalBeanDefinition(beanName)
Spring 5 AbstractBeanFactory – getMergedLocalBeanDefinition 源码解析
getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd)
Spring 5 AbstractBeanFactory – getMergedLocalBeanDefinition 源码解析
predictBeanType(dbd.getBeanName(), tbd);
预测mdb所指的bean的最终bean类型(已处理bean实例的类型)。大概逻辑:
- 如果成功获取到mbd的目标类型【RootBeanDefinition#getTargetType】,就将其返回出去
- 如果mbd有设置mbd的工厂方法名,则直接返回 null
- 返回resolveBeanClass(RootBeanDefinition,String,Class<?>…)的执行结果, 主要是为mbd解析bean类,将beanName解析为Class引用(如果需要),并将解析后的Class存储 在mbd中以备将来使用。
/**
* Predict the eventual bean type (of the processed bean instance) for the
* specified bean. Called by {@link #getType} and {@link #isTypeMatch}.
* Does not need to handle FactoryBeans specifically, since it is only
* supposed to operate on the raw bean type.
* <p>预测指定bean的最终bean类型(已处理bean实例的类型)。
* 通过调用getType和isTypeMatch。不需要专门处理FactoryBeans,因为它仅应在
* 原始bean类型上运行</p>
* <p>This implementation is simplistic in that it is not able to
* handle factory methods and InstantiationAwareBeanPostProcessors.
* It only predicts the bean type correctly for a standard bean.
* To be overridden in subclasses, applying more sophisticated type detection.
* <p>此实现非常简单,因为它无法处理工厂方法和InstantiationAwareBeanProcess.
* 它只能为标准Bean正确预测Bean类型。要在子类中覆盖,请应用更复杂的类型检查</p>
* @param beanName the name of the bean -- bean名,用于发生异常时,描述异常信息
* @param mbd the merged bean definition to determine the type for
* -- 合并的bean定义以确定其类型
* @param typesToMatch
* 要匹配的类型,用于当该工厂有临时类加载器且该类加载器属于DecoratingClassLoader实例时,
* 对这些要匹配的类型进行在临时类加载器中的排除,以交由父ClassLoader以常规方式处理
* 默认情况下父classLoader是线程上下文类加载器】
* <br/>
* the types to match in case of internal type matching purposes
* (also signals that the returned {@code Class} will never be exposed to application code)
* -- 内部类型培评时要匹配的类型(也表示返回的Class永远不会保留应用程序代码)
* @return the type of the bean, or {@code null} if not predictable
* -- Bean的类型;如果不可预测,则为null
*/
@Nullable
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
//获取mbd的目标类型
Class<?> targetType = mbd.getTargetType();
//如果成功获得mbd的目标类型
if (targetType != null) {
//返回 mbd的目标类型
return targetType;
}
//如果有设置mbd的工厂方法名
if (mbd.getFactoryMethodName() != null) {
//返回null,表示不可预测
return null;
}
//为mbd解析bean类,将beanName解析为Class引用(如果需要),并将解析后的Class存储在mbd中以备将来使用。
return resolveBeanClass(mbd, beanName, typesToMatch);
}