bean加载二:递归beandefinition、初始化依赖

当从第三步没有获取到对应的bean,也就是不存在循环依赖以及重复获取bean的情况下,就会走接下来的4、5、6、7这几个步骤实例化以及初始化对象。

4 parentBeanFactory和依赖处理

4.1 isPrototypeCurrentlyInCreation

protected boolean isPrototypeCurrentlyInCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        return (curVal != null &&
                (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
    }

其中 prototypesCurrentlyInCreation 在后面的第7步,除单例模式外创建类实例时添加缓存。也就是用来判断原型模式下的循环依赖

4.2 parentBeanFactory

// Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
// 原型模式是每次获取创建一个新的对象,所以不能通过缓存来解决循环依赖问题
if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
}

// Check if bean definition exists in this factory.
// 如果容器中没有找到,则从父类容器中加载
// <4>
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果父容器不为空,并且 beandefinition 不存在
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // Not found -> check parent.
    String nameToLookup = originalBeanName(name);
    // 如果,父类容器为 AbstractBeanFactory ,直接递归查找
    if (parentBeanFactory instanceof AbstractBeanFactory) {
        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                nameToLookup, requiredType, args, typeCheckOnly);
    }
    // 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象
    else if (args != null) {
        // Delegation to parent with explicit args.
        return (T) parentBeanFactory.getBean(nameToLookup, args);
    }
    // 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象
    else if (requiredType != null) {
        // No args -> delegate to standard getBean method.
        return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
    // 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象
    else {
        return (T) parentBeanFactory.getBean(nameToLookup);
    }
}

这段代码主要有两个逻辑:
1.检测。若当前 bean 在创建,则抛出 BeanCurrentlyInCreationException 异常。
2.如果 beanDefinitionMap 中不存在 beanName 的 BeanDefinition(即在 Spring bean 初始化过程中没有加载),则尝试从 parentBeanFactory 中加载。



这里的 parentBeanFactory 来源于xml配置中的 parent 属性,当 parent 不为空,并且当前beanfactory不包含对应beanName的beandefinition对象时,从 parentBeanFactory 中通过不同的方式创建对应的bean对象。

4.3 markBeanAsCreated

protected void markBeanAsCreated(String beanName) {
    //没有创建
    if (!this.alreadyCreated.contains(beanName)) {
        // 加上全局锁
        synchronized (this.mergedBeanDefinitions) {
            // 再次检查一次:DCL 双检查模式
            if (!this.alreadyCreated.contains(beanName)) {
                // 从 mergedBeanDefinitions 中删除 beanName,
                // 并在下次访问时重新创建它。
                // Let the bean definition get re-merged now that we're actually creating
                // the bean... just in case some of its metadata changed in the meantime.
                clearMergedBeanDefinition(beanName);
                // 添加到已创建 bean 集合中
                this.alreadyCreated.add(beanName);
            }
        }
    }
}

主要用于标记 beanName 正在创建中

5 getMergedLocalBeanDefinition

主要用于合并父beandefinition的属性,如 scope,classname等属性

6 初始化依赖的其他bean

String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        // 检验依赖的 bean 是否已经注册给当前 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);
        }
    }
}

这里主要是三个部分

6.1 isDependent

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) {
    if (alreadySeen != null && alreadySeen.contains(beanName)) {
        return false;
    }
    // 解析 beanName 别名
    String canonicalName = canonicalName(beanName);
    // 获取依赖的 beanNames
    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.add(beanName);
        if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
        }
    }
    return false;
}

判断beanName是否依赖dependentBeanName

6.2 registerDependentBean

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

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

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

保存beanName与其依赖的bean的对应关系,以便在beanName销毁之前先销毁其依赖的bean

6.3 getBean(dep)

创建对应的依赖bean

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。