BeanDefinition 的合并
Spring 在使用 BeanDefinition 创建 Bean 之前,会对 BeanDefinition 进行合并和检查。这部分代码位于 AbstractBeanFactory#getMergedLocalBeanDefinition 中
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
//合并好的BeanDefinition的缓存
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
//获取一个beanName的合并BeanDefinition ,一般都是调用此方法
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
//1 检查缓存
// 没有 或者 过期了则重新合并
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
// 2 合并BeanDefinition
// 先调用 getBeanDefinition方法,getBeanDefinition方法并不会进行合并,而是一直保持BeanDefintion最初定义时候的样子
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
//再套一层
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
//最终合并BeanDefinition的方法
// beanName bean的名字
// bd 原始的BeanDefinition
// containingBd 如果是内部bean,则包含bean定义,如果是顶级bean,则为null
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
//0 整体代码加锁,多线程场景下,同一beanName被多个线程调用合并方法时,造成合并的不一致
synchronized (this.mergedBeanDefinitions) {
// mbd 最终的合并结果
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;//如果是重新合并的,则此时mbd不会为null,mbd.stale为true,此时使用一个previous来保持对合并前的
// 1 如果没有父定义,则不需要合并,稍微包装下就可以返回
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition rootBeanDef) {
mbd = rootBeanDef.cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// 2 有父定义,需要进行递归合并
BeanDefinition pbd;//父定义
try {
String parentBeanName = transformedBeanName(bd.getParentName());
// 当前beanName不等于arentBeanName,则递归调用最上层的getMergedBeanDefinition方法,即把父定义递归合并好
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
// 如果重名,则应该是在父容器中,则去父容器中去寻找,如果没有父容器,说明出现了错误的配置,即自己的parent就是自己!需要抛出异常
if (getParentBeanFactory() instanceof ConfigurableBeanFactory parent) {
pbd = parent.getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {//这里说明引用了一个不存在的父BeanDefinition
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
//3 Deep copy with overridden values.
//把父定义的属性深拷贝一份
mbd = new RootBeanDefinition(pbd);
//4 把当前BeanDefintion的属性覆盖写到mbd中
mbd.overrideFrom(bd);
}
//5 设置缺失属性 scope=单例
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// 6 如果容器Bean不是单例的,而当前Bean是单例的,那么当前Bean的scope需要变成与容器Bean相同
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// 7 缓存合并好的BeanDefinition
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
//把旧BeanDefintion的一些特殊属性复制到新的BeanDefintion上
private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous, RootBeanDefinition mbd) {
if (ObjectUtils.nullSafeEquals(mbd.getBeanClassName(), previous.getBeanClassName()) &&
ObjectUtils.nullSafeEquals(mbd.getFactoryBeanName(), previous.getFactoryBeanName()) &&
ObjectUtils.nullSafeEquals(mbd.getFactoryMethodName(), previous.getFactoryMethodName())) {
ResolvableType targetType = mbd.targetType;
ResolvableType previousTargetType = previous.targetType;
if (targetType == null || targetType.equals(previousTargetType)) {
mbd.targetType = previousTargetType;
mbd.isFactoryBean = previous.isFactoryBean;
mbd.resolvedTargetType = previous.resolvedTargetType;
mbd.factoryMethodReturnType = previous.factoryMethodReturnType;
mbd.factoryMethodToIntrospect = previous.factoryMethodToIntrospect;
}
}
}
}