Spring源码解析之从处理依赖depends-on

这篇文章分析的代码:

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

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                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 {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            //如果不是仅仅做类型检查则是创建bean,这里需要记录 将beanName缓存在alreadyCreatedz中
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

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

                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    //获取depends-on的属性值,如果depends-on的值存在 则添加进入dependentBeanMap缓存中
                    for (String dep : dependsOn) {
                        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);
                        }
                    }
                }

这段代码处理的逻辑是:

  • 如果bean是原型模式并处于创建中,则抛出异常。
  • 如果beanDefinitionMap中不存在对应beanName的BeanDefinition,那么尝试从parentBeanFactory中加载。
  • 判断是否检查类型
  • 从 mergedBeanDefinitions 中获取 beanName 对应的 RootBeanDefinition
  • 检查dependes-on依赖

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))));
	}

Spring对于处于原型模式的正在创建的bean的依赖会抛出异常。

 

2.pareentBeanFactory加载

BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
	//获取原始name
	String nameToLookup = originalBeanName(name);
	if (parentBeanFactory instanceof AbstractBeanFactory) {
		//加入parentBeanFactory是AbstractBeanFactory类型
		return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
				nameToLookup, requiredType, args, typeCheckOnly);
	}
	else if (args != null) {
		//args不为空情况下,委托方法
		return (T) parentBeanFactory.getBean(nameToLookup, args);
	}
	else {
		////标准情况下,委托方法
		return parentBeanFactory.getBean(nameToLookup, requiredType);
	}
}

如果beanDefinitionMap没有包含beanName对应的BeanDefinition,则从parentBeanFactory中加载。

originalBeanName()方法作用:如果name是以&开头的,那么beanName也要加上这个标志。

 

3.类型检查

参数typeCheckOnly判断bean是否为类型检查获取bean。如果不是则需要调用markBeanAsCreated()缓存起来.

protected void markBeanAsCreated(String beanName) {
	//判断已创建是否包含beanName
	if (!this.alreadyCreated.contains(beanName)) {
	    // 获取全局锁
		synchronized (this.mergedBeanDefinitions) {
		    //双重判断
			if (!this.alreadyCreated.contains(beanName)) {
			     // 从 mergedBeanDefinitions 中删除 beanName,
                 // 并在下次访问时重新创建它。
				clearMergedBeanDefinition(beanName);
				// 添加到已创建bean 集合中
				this.alreadyCreated.add(beanName);
			}
		}
	}
}

 

4. 获取RootBeanDefinition

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

getMergedLocalBeanDefinition():作用主要是将获取beanName对应的RootBeanDefinition对象

checkMergedBeanDefinition()则是检查创建的RootBeanDefinition对象。

 

5.处理depends-on

 String[] dependsOn = mbd.getDependsOn();
 if (dependsOn != null) {
     //获取depends-on的属性值,如果depends-on的值存在 则添加进入dependentBeanMap缓存中
     for (String dep : dependsOn) {
         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);
         }
     }
 }
 // 单例模式下创建bean

处理bean的依赖思路大致是:

  • 获取depends-on依赖,如果depends-on不为空,检查beanName和依赖是否已经存在依赖关系。
  • 如果存在抛出异常,不存在则缓存对应的依赖。

isDependent方法:检测beaName和dependsOn是否存在已存在依赖。

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
        if (alreadySeen != null && alreadySeen.contains(beanName)) {
            return false;
        }
        //获取原始的beanName
        String canonicalName = canonicalName(beanName);
        //获取beaName的依赖集合
        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;
    }

registerDependentBean方法注册bean的依赖关系

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);
		}
	}

将依赖映射关系保存:dependentBeanMap、dependenciesForBeanMap。

最后调用getBean()实例化bean。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章