相关源码注释
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 源码注释
getMergedLocalBeanDefinition
获取beanName合并后的本地RootBeanDefintiond
- 优先从合并BeanDefinitionMap缓存【mergedBeanDefinitions】中获取,获取到的 RootBeanDefinition对象只要没有标记为重新合并定义的,都会返回出去
- 获取beanName在该工厂所指的BeanDefinition对象,传入getMergedBeanDefinition(beanName,BeanDefinition) 方法,将该方法的返回结果返回出去
/**
* Map from bean name to merged RootBeanDefinition.
* <p>从bean名称映射到合并的RootBeanDefinition</p>
* */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
/**
* Return a merged RootBeanDefinition, traversing the parent bean definition
* if the specified bean corresponds to a child bean definition.
* <p>返回合并的RootBeanDefinition,如果指定的bean对应于子bean定义,则遍历父bean定义。</p>
* @param beanName the name of the bean to retrieve the merged definition for
* -- 用于检索其合并定义的bean名
* @return a (potentially merged) RootBeanDefinition for the given bean
* -- 结合bean的(可能合并的)RootBeanDefinition
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* -- 如果某给定名称的bean
* @throws BeanDefinitionStoreException in case of an invalid bean definition
* -- 如果bena定义无效
*/
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
//首先以最小的锁定快速检测并发映射。
//从 bean名称映射到合并的RootBeanDefinition的集合 中获取beanName对应的RootBeanDefinition
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
//如果mbd不为null 且 不需要重新合并定义
if (mbd != null && !mbd.stale) {
//返回对应的RootBeanDefinition
return mbd;
}
//获取beanName对应的合并Bean定义,如果beanName对应的BeanDefinition是子BeanDefinition,
// 则通过与父级合并返回RootBeanDefinition
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
getBeanDefinition(beanName)
获取该工厂beanName的BeanDefinition对象
org.springframework.beans.factory.support.AbstractBeanFactory # getBeanDefinition(String beanName) 是个抽象方法:
/**
* Return the bean definition for the given bean name.
* <p>返回给定bean名称的bean定义</p>
* Subclasses should normally implement caching, as this method is invoked
* by this class every time bean definition metadata is needed.
* <p>子类通常应实现缓存,因为每次需要bean定义元数据时,此类便会调用此方法</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 find a definition for
* -- 用于查找定义的bean的名称
* @return the BeanDefinition for this prototype name (never {@code null})
* -- 此原型名称的BeanDefinition(永远不为{@code null})
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
* if the bean definition cannot be resolved
* -- 如果无法解析bean定义
* @throws BeansException in case of errors -- 如果有错误
* @see RootBeanDefinition
* @see ChildBeanDefinition
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
*/
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
由 org.springframework.beans.factory.support.DefaultListableBeanFactory 实现
1. 从该工厂的BeanDefinitionMap缓存【beanDefinitionMap】中获取beanName 的BeanDefinition对象【忽略父级工厂】
2. 获取不到时,打印日志并抛出NoSuchBeanDefinitionException
/**
* Map of bean definition objects, keyed by bean name.
* <p>Bean定义对象的映射,以Bean名称为键</p>
* */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/**
* 获取该工厂beanName的BeanDefinition对象:
* @param beanName name of the bean to find a definition for -- 查找定义的bean名称
*/
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
//从 Bean定义对象的映射 中获取beanName对应的BeanDefinition对象
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
//如果从 Bean定义对象的映射 没有找到
if (bd == null) {
//如果当前日志级别为跟踪
if (logger.isTraceEnabled()) {
//打印日志 : 在DefaultListBeanFactory中没有找到名为 beanName 的bean
logger.trace("No bean named '" + beanName + "' found in " + this);
}
//抛出没有此类bean异常
throw new NoSuchBeanDefinitionException(beanName);
}
//返回beanName对应的BeanDefinition对象
return bd;
}
getMergedBeanDefinition(beanName, getBeanDefinition(beanName))
获取beanName对应的合并后的RootBeanDefinition
- 该方法时线程安全的,使用 合并后的RootBeanDefinitionMap缓存 【mergedBeanDefinitions】进行加锁
- 尝试从mergedBeanDefinitions中获取beanName合并后的RootBeanDefinition,【mdb】。如果mbd为null 或者 mbd需要重新合并定义,(在mdb需要重新合并定义情况下,会对mdb赋值到【pervious】,用于来与新的mbd进行合并) 会通过下面的方式尽可能的获取或构造出mbd,也就是说mbd就是合并后的RootBeanDefinition:
- 在bd没有父级Bean名下:
- 如果bd是RootBeanDefinition,mdb就是bd的副本
- 如果bd不是RootBeanDefinition,就对bd的属性进行深度克隆到一个新的RootBeabDefinition 再赋值给mdb
- 如果bd有父级Bean名
- 获取bd的父级Bean对应的最终别名【parentBeanName】
- 如果beanName不等于parentBeanName,就获取parentBeanName合并后的BeanDefinition【pdb】
- 否则,就会获取该工厂的父工厂:
- 如果父工厂是 ConfigurableBeanFactory的实例,使用父工厂获取parentBeanName 合并后的BeanDefinition赋值给pdb
- 否则抛出NoSuchBeanDefinitionException
- 就对pbd的属性进行深度克隆到一个新的RootBeabDefinitiond复制给mdb
- 使用bd的信息覆盖mbd
- 获取bd的父级Bean对应的最终别名【parentBeanName】
- 在bd没有父级Bean名下:
- 如果mbd没有设置作用域,会对mbd设置默认作用域,默认是单例
- 如果传入了contatiningBd,就以contatingBd的作用域作为mbd的作用域
- 如果没有传入containingBd且当前工厂是同意缓存bean元数据,就会将beanName和mbd的映射关系添加到 合并后的RootBeanDefinitionMap缓存中【mergedBeanDefinitions】
- 如果previous不为null,也就是mdb需要重新合并定义,就会调用 copyRelevantMergedBeanDefinitionCaches(previous, mbd)让mbd与previous进行合并。
/**
* Map from bean name to merged RootBeanDefinition.
* <p>从bean名称映射到合并的RootBeanDefinition</p>
* */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
/**
* <p>获取beanName对应的合并后的RootBeanDefinition:直接交给
* getMergedBeanDefinition(String, BeanDefinition,BeanDefinition)处理,第三个参数
* 传null</p>
* 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.
* <p>如果给定RootBeanDefinition是子BeanDefinition,则通过与父级合并返回
* RootBeanDefinition</p>
* @param beanName the name of the bean definition -bean定义名称
* @param bd the original bean definition (Root/ChildBeanDefinition)
* -- 原始BeanDefinition(Root/ChildBeanDefinition)
* @return a (potentially merged) RootBeanDefinition for the given bean
* -- 给定bean的(可能合并的)RootBeanDefinition
* @throws BeanDefinitionStoreException in case of an invalid bean definition
* -- 如果Bean定义无效
*/
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
/**
* Return a RootBeanDefinition for the given bean, by merging with the
* parent if the given bean's definition is a child bean definition.
* <p>如果给定RootBeanDefinition是子BeanDefinition,则通过与父级合并返回
* RootBeanDefinition</p
* @param beanName the name of the bean definition -bean定义名称
* @param bd the original bean definition (Root/ChildBeanDefinition)
* -- 原始BeanDefinition(Root/ChildBeanDefinition)
* @param containingBd the containing bean definition in case of inner bean,
* or {@code null} in case of a top-level bean
* -- 如果是内部bean,则为包含bean的定义;如果是顶级bean,则为null
* @return a (potentially merged) RootBeanDefinition for the given bean
* -- 给定bean的(可能合并的)RootBeanDefinition
* @throws BeanDefinitionStoreException in case of an invalid bean definition
* -- 如果Bean定义无效
*/
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
//同步: 使用 从bean名称映射到合并的RootBeanDefinition集合 进行加锁
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
//该变量表示从bean名称映射到合并的RootBeanDefinition集合中取到的mbd且该mbd需要重新合并定义
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
// 立即检查完全锁定,以强制执行相同的合并实例
//如果没有 包含bean定义
if (containingBd == null) {
//从 从bean名称映射到合并的RootBeanDefinition集合 中获取beanName对应的
// BeanDefinition 作为 mbd
mbd = this.mergedBeanDefinitions.get(beanName);
}
//如果mbd为null 或者 mdb需要重新合并定义
if (mbd == null || mbd.stale) {
//将mdn作为previous
previous = mbd;
//将mdb置空
mbd = null;
//如果获取不到 原始BeanDefinition 的父Bean名
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
// 使用给定的 RootBeanDefinition的副本
//如果 原始BeanDefinition 是 RootBeanDefinition 对象
if (bd instanceof RootBeanDefinition) {
//克隆一份bd的Bean定义赋值给mdb
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
// 创建一个新的RootBeanDefinition作为bd的深层副本并赋值给mbd
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
// 子bean定义:需要与父bean合并
//定义一个父级BeanDefinition变量
BeanDefinition pbd;
try {
//获取bd的父级Bean对应的最终别名
String parentBeanName = transformedBeanName(bd.getParentName());
//如果当前bean名不等于父级bean名
if (!beanName.equals(parentBeanName)) {
//获取parentBeanName的"合并的"BeanDefinition赋值给pdb
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
//当前bean名等于父级bean名
//获取父工厂
BeanFactory parent = getParentBeanFactory();
//如果父工厂是 ConfigurableBeanFactory的实例
if (parent instanceof ConfigurableBeanFactory) {
//使用父工厂获取parentBeanName对应的合并BeanDefinition赋值给pdb
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
//如果父工厂不是ConfigurableBeanFactory
//抛出没有此类bean定义异常,父级bean名为parentBeanName 等于 名为 beanName的bean名;
// 没有AbstractBeanFactory父级无法解决
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
//捕捉没有此类bean定义异常
//抛出 当BeanFactory遇到无效的bean定义时引发的异常 :
// 无法解析父bean定义 'bd的父bean定义名'
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// 具有覆盖值的深层赋值
// 以bd的父级bean定义对象作为根Bean定义对象
mbd = new RootBeanDefinition(pbd);
// 使用原始bd定义信息覆盖父级的定义信息:
// 1. 如果在给定的bean定义中指定,则将覆盖beanClass
// 2. 将始终从给定的bean定义中获取abstract,scope,lazyInit,autowireMode,
// dependencyCheck和dependsOn
// 3. 将给定bean定义中ConstructorArgumentValues,propertyValues,
// methodOverrides 添加到现有的bean定义中
// 4. 如果在给定的bean定义中指定,将覆盖factoryBeanName,factoryMethodName,
// initMethodName,和destroyMethodName
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
// 设置默认的单例作用域(如果之前未配置)
//如果mbd之前没有配置过作用域
if (!StringUtils.hasLength(mbd.getScope())) {
//设置mbd的作用域为单例
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
// 非单例bean中包含的bean本身不能是单例。
// 让我们在此即时进行更正,因为这可能是外部bean的父子合并的结果,在这种情况下,
// 原始内部bean定义将不会继承合并的外部bean的单例状态。
// 如果有传包含bean定义且包含bean定义不是单例但mbd又是单例
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
//让mbd的作用域设置为跟containingBd的作用域一样
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
// 暂时缓存合并的bean定义
// (稍后可能仍会重新合并以获取元数据更正)
//如果没有传入包含bean定义 且 当前工厂是同意缓存bean元数据
if (containingBd == null && isCacheBeanMetadata()) {
//将beanName和mbd的关系添加到 从bean名称映射到合并的RootBeanDefinition集合中
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
//如果存在 上一个 从bean名称映射到合并的RootBeanDefinition集合中 取出的mbd
// 且该mbd需要重新合并定义
if (previous != null) {
//拿previous来对mdb进行重新合并定义:
//1. 设置mbd的目标类型为previous的目标类型
//2. 设置mbd的工厂bean标记为previous的工厂bean标记
//3. 设置mbd的用于缓存给定bean定义的确定的Class为previous的用于缓存给定bean定义的确定的Class
//4. 设置mbd的工厂方法返回类型为previous的工厂方法返回类型
//5. 设置mbd的用于缓存用于自省的唯一工厂方法候选为previous的用于缓存用于自省的唯一工厂方法候选
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
transformedBeanName(bd.getParentName())
去除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名称【可能是全类名】
/**
* Cache from name with factory bean prefix to stripped name without dereference.
* <p>从具有FactoryBean前缀的名称缓存到剥离的名称,而无需取消引用</p>
* @since 5.1
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();
/**
* 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;
});
}
((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
/**
* Return a 'merged' BeanDefinition for the given bean name,
* merging a child bean definition with its parent if necessary.
* <p>返回给定bean名的"合并的"BeanDefinition,如有必要,将子bean定义与其
* 父对象合并。</p>
* <p>This {@code getMergedBeanDefinition} considers bean definition
* in ancestors as well.
* <p>这个{@code getMergedBeanDefinition}也考虑祖先的bean定义。</p>
* @param name the name of the bean to retrieve the merged definition for
* (may be an alias) - 用于检索合并定义的bean名称(可以是别名)
* @return a (potentially merged) RootBeanDefinition for the given bean
* -- 给定bean的(可能合并的)RootBeanDefinition
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* -- 如果没有给定名称的bean
* @throws BeanDefinitionStoreException in case of an invalid bean definition
* -- 如果bean定义无效
*/
@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
//获取name对应的规范名称【全类名】
String beanName = transformedBeanName(name);
// Efficiently check whether bean definition exists in this factory.
// 有效检查该工厂中是否存在bean定义。
// 如果当前bean工厂不包含具有beanName的bean定义 且 父工厂是ConfigurableBeanFactory的实例
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
//使用父工厂返回beanName的合并BeanDefinition【如有必要,将子bean定义与 其父级合并】
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
}
// Resolve merged bean definition locally.
//本地解决合并的bean定义
return getMergedLocalBeanDefinition(beanName);
}
isCacheBeanMetadata()
/**
* Whether to cache bean metadata or rather reobtain it for every access.
* <p>是否缓存bean元数据还是每次访问重新获取它</p>
* */
private boolean cacheBeanMetadata = true;
@Override
public void setCacheBeanMetadata(boolean cacheBeanMetadata) {
this.cacheBeanMetadata = cacheBeanMetadata;
}
@Override
public boolean isCacheBeanMetadata() {
return this.cacheBeanMetadata;
}
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
复制相关的合并bean定义缓存,或者说拿previous来对mdb进行重新合并定义。
- 设置mbd的目标类型为previous的目标类型
- 设置mbd的工厂bean标记为previous的工厂bean标记
- 设置mbd的用于缓存给定bean定义的确定的Class为previous的用于缓存给定bean定义的确定的Class
- 设置mbd的工厂方法返回类型为previous的工厂方法返回类型
- 设置mbd的用于缓存用于自省的唯一工厂方法候选为previous的用于缓存用于自省的唯一工厂方法候选
/**
* 复制相关的合并bean定义缓存,或者说拿previous来对mdb进行重新合并定义。
* @param previous 原需要重新合并定义mbd
* @param mbd 当前mbd
*/
private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous, RootBeanDefinition mbd) {
//ObjectUtils.nullSafeEquals:确定给定的对象是否相等,如果两个都为null返回true ,
// 如果其中一个为null,返回false
//mbd和previous的当前Bean类名称相同,工厂bean名称相同,工厂方法名相同
if (ObjectUtils.nullSafeEquals(mbd.getBeanClassName(), previous.getBeanClassName()) &&
ObjectUtils.nullSafeEquals(mbd.getFactoryBeanName(), previous.getFactoryBeanName()) &&
ObjectUtils.nullSafeEquals(mbd.getFactoryMethodName(), previous.getFactoryMethodName())) {
//获取mbd的目标类型
ResolvableType targetType = mbd.targetType;
//获取previous的目标类型
ResolvableType previousTargetType = previous.targetType;
//如果mdb的目标类型为null 或者 mdb的目标类型与previous的目标类型相同
if (targetType == null || targetType.equals(previousTargetType)) {
//设置mbd的目标类型为previous的目标类型
mbd.targetType = previousTargetType;
//设置mbd的工厂bean标记为previous的工厂bean标记
mbd.isFactoryBean = previous.isFactoryBean;
//设置mbd的用于缓存给定bean定义的确定的Class为previous的用于缓存给定bean定义的确定的Class
mbd.resolvedTargetType = previous.resolvedTargetType;
//设置mbd的工厂方法返回类型为previous的工厂方法返回类型
mbd.factoryMethodReturnType = previous.factoryMethodReturnType;
//设置mbd的用于缓存用于自省的唯一工厂方法候选为previous的用于缓存用于自省的唯一工厂方法候选
mbd.factoryMethodToIntrospect = previous.factoryMethodToIntrospect;
}
}
}