4 parentBeanFactory 与依赖处理

607 阅读3分钟

接上文,如果我们从单例缓存中没有获取到我们想要的bean,那么只会有以下2种情况

  • 不是单例bean
  • 是单例bean,但是还没有初始化完成
 代码位置org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

// <1> Spring 只解决单例模式下得循环依赖,在原型模式下的循环依赖直接抛出异常。
if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
}

// <2> 如果容器中没有找到该bean,则从父类容器中加载
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    
    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);
    }
}

// <3> 记录创建bean的记录
if (!typeCheckOnly) {
    markBeanAsCreated(beanName);
}

try {
    // <4> 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    // 检查给定的合并的 BeanDefinition
    checkMergedBeanDefinition(mbd, beanName, args);

    // Guarantee initialization of beans that the current bean depends on.
    // <5> 处理所依赖的 bean
    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
        for (String dep : dependsOn) {
            // 若给定的依赖 bean 已经注册为依赖给定的 bean
            // 循环依赖的情况
            if (isDependent(beanName, dep)) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
            }
            // 缓存依赖调用
            registerDependentBean(dep, beanName);
            try {
                getBean(dep);
            } catch (NoSuchBeanDefinitionException ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
            }
        }
    }
}

1 检测是否是原型bean

if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
}

//判断原型bean是否是创建过程中
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        return curVal != null && (curVal.equals(beanName) || curVal instanceof Set && ((Set)curVal).contains(beanName));
    }
    

//定义
private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal("Prototype beans currently in creation");
  • isPrototypeCurrentlyInCreation() 来判断是否是正在创建中
  • this.prototypesCurrentlyInCreation 是一个集合,存放正在创建的bean,和单例bean缓存的思路一样,但是实现方式却不一样,单例bean缓存是用set来实现的,原型模式则是用ThreadLocal 实现

2 检查parentBeanFactory

// 获取 parentBeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
// parentBeanFactory 不为空且 beanDefinitionMap 中不存该 name 的 BeanDefinition
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // 确定原始 beanName
    String nameToLookup = originalBeanName(name);
    // 若为 AbstractBeanFactory 类型,委托父类处理
    if (parentBeanFactory instanceof AbstractBeanFactory) {
        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                nameToLookup, requiredType, args, typeCheckOnly);
    } else if (args != null) {
        // 委托给构造函数 getBean() 处理
        return (T) parentBeanFactory.getBean(nameToLookup, args);
    } else {
        // 没有 args,委托给标准的 getBean() 处理
        return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
}


//获取parentBeanFactory
public BeanFactory getParentBeanFactory() {
    return this.parentBeanFactory;
}
    
  • 这段代码不是很复杂,前面需要先获取 parentBeanFactory,如果不为null 且 beanDefinitionMap存在该name的BeanDefinition,则进行创建
  • 如果满足上述条件,首先要获取原始的beanName
org.springframework.beans.factory.support.AbstractBeanFactory#originalBeanName

protected String originalBeanName(String name) {
	String beanName = transformedBeanName(name);
	if (name.startsWith(FACTORY_BEAN_PREFIX)) { 
		beanName = FACTORY_BEAN_PREFIX + beanName;
	}
	return beanName;
}

protected String transformedBeanName(String name) {
    return this.canonicalName(BeanFactoryUtils.transformedBeanName(name));
}


org.springframework.beans.factory.BeanFactoryUtils#transformedBeanName
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");

    String beanName;
    for(beanName = name; beanName.startsWith("&"); beanName = beanName.substring("&".length())) {
    }

    return beanName;
}

org.springframework.core.SimpleAliasRegistry#canonicalName

public String canonicalName(String name) {
   String canonicalName = name;

    String resolvedName;
    do {
        resolvedName = (String)this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    } while(resolvedName != null);

    return canonicalName;
}

  • SimpleAliasRegistry#canonicalName 是对name进行转换,获取真正的beanName,主要是对 aliasBean的转换
  • 如果name是以"&"开头,则加上"&",这么做的目的是因为 BeanFactoryUtils#transformedBeanName 将name中的 "&"删除了,此处只是进行补偿
  • 剩下的就是根据不同的参数,父类进行初始化

3 添加创建记录

//  已创建 Bean 的名字集合  位于org.springframework.beans.factory.support.AbstractBeanFactory#alreadyCreated
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));


protected void markBeanAsCreated(String beanName) {
    // 如果没有创建
    if (!this.alreadyCreated.contains(beanName)) {
        // 加上全局锁,但是为啥锁这个集合呢?
        synchronized (this.mergedBeanDefinitions) {
            // 再次检查一次:DCL 双检查模式
            if (!this.alreadyCreated.contains(beanName)) {
                // 从 mergedBeanDefinitions 中删除 beanName,并在下次访问时重新创建它。
                clearMergedBeanDefinition(beanName);
                // 添加到已创建 bean 集合中
                this.alreadyCreated.add(beanName);
            }
        }
    }
}

protected void clearMergedBeanDefinition(String beanName) {
    this.mergedBeanDefinitions.remove(beanName);
}

4 获取RootBeanDefinition

// org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition
// 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);


 protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    //从缓存中获取,如果不为空,则直接返回
    RootBeanDefinition mbd = (RootBeanDefinition)this.mergedBeanDefinitions.get(beanName);
    if (mbd != null) {
        return mbd;
    }
    // 获取 RootBeanDefinition,
    // 如果返回的 BeanDefinition 是子类 bean 的话,则合并父类相关属性
    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

 protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args) throws BeanDefinitionStoreException {
    if (mbd.isAbstract()) {
        throw new BeanIsAbstractException(beanName);
    }
}

  • 首先 从 mergedBeanDefinitions 获取beanName对应的 RootBeanDefinition,若存在直接返回,否则 通过 getMergedBeanDefinition 尝试回去,(getMergedBeanDefinition 该方法太长,后续再补充)
  • 通过 checkMergedBeanDefinition 检查得到的mbd

5 对依赖进行处理

String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        // 若给定的依赖 bean 已经注册为依赖给定的 bean
        // 循环依赖的情况
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        // 缓存依赖调用
        registerDependentBean(dep, beanName);
        try {
            //地柜处理
            getBean(dep);
        } catch (NoSuchBeanDefinitionException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
        }
    }
}



/**
 * org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#isDependent(java.lang.String, java.lang.String)
 * 保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
 */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

protected boolean isDependent(String beanName, String dependentBeanName) {
	synchronized (this.dependentBeanMap) {
		return isDependent(beanName, dependentBeanName, null);
	}
}


private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
    // alreadySeen 已经检测的依赖 bean
    if (alreadySeen != null && alreadySeen.contains(beanName)) {
        return false;
    }
    // 获取原始 beanName
    String canonicalName = canonicalName(beanName);
    // 获取当前 beanName 的依赖集合
    Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
    if (dependentBeans == null) {
        return false;
    }
    // 存在,则证明存在已经注册的依赖
    if (dependentBeans.contains(dependentBeanName)) {
        return true;
    }
    // 递归检测依赖
    for (String transitiveDependency : dependentBeans) {
        if (alreadySeen == null) {
            alreadySeen = new HashSet<>();
        }
        // 添加到 alreadySeen 中
        alreadySeen.add(beanName);
        // 递推
        if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
        }
    }
    return false;
}
  • 通过 mbd.getDependsOn() 获取该mbd的所有依赖

6 gisterDependentBean

/**
 * 
 * 保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
 */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

/**
 *
 * 保存的是依赖 beanName 之间的映射关系:依赖 beanName - > beanName 的集合
 */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

public void registerDependentBean(String beanName, String dependentBeanName) {
    // 获取 beanName
    String canonicalName = canonicalName(beanName);

    // 添加 <canonicalName, <dependentBeanName>> 到 dependentBeanMap 中
    synchronized (this.dependentBeanMap) {
        Set<String> dependentBeans =
                this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }

    // 添加 <dependentBeanName, <canonicalName>> 到 dependenciesForBeanMap 中
    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean =
                this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        dependenciesForBean.add(canonicalName);
    }
}