else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//3.因为spring只支持解决单例模式下的循环依赖,所以原型模式下会抛出异常。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
/**
* 执行到这里说明在上面没有获取到bean,分为两种情况
* 1.要获取的bean不是单例的
* 2.bean是单例,但是还在加载的过程中
*/
//4.如果容器中没有找到就从父类容器中加载
BeanFactory parentBeanFactory = getParentBeanFactory();
//这里有个问题,什么时候,beanname是不会在BeanDefinition里面的呢
//这里应该是指不在自己的BeanDefinitionMap里但是在父类的里面
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//验证方法注入
//确定原始beanName,如果去掉了前缀就把前缀给加回来
String nameToLookup = originalBeanName(name);
//父类若为AbstractBeanFactory,那么委托父类进行加载
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);
}
}
//5.表示是否为仅仅进行类型检查获取 Bean 对象。
// 如果不是仅仅做类型检查,而是创建 Bean 对象,就要执行以下的逻辑
//这个值是false,代表这个if一定会执行。
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//6.从容器中获取beanname对应的 GenericBeanDefinition 对象,
// 并将其转换为 RootBeanDefinition 对象,转换的原因是RootBeanDefinition是子类
//它提供了更多的方法供之后使用
//这里提到的合并BeanDefinition指的是将beanName对应的子类的BeanDefinition
//与父类RootBeanDefinition的属性融合,得到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();
//7.处理所依赖的bean
//注意这里的依赖指的并不是循环依赖里面的那个依赖,这个说的应该是@dependsOn这个属性,用来
//指定Bean加载的顺序的
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 {
//递归处理依赖bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
什么情况会执行到这里,第一:待获取到bean不是单例 第二:待获取的bean是单例,但是还在创建之中
这段代码主要做了以下的事:
mergedBeanDefinitions
中获取 beanName
对应的 RootBeanDefinition 对象。如果这个 BeanDefinition 是子 Bean 的话,则会合并父类的相关属性。下面将分别解析这个5个地方
//3.因为spring只支持解决单例模式下的循环依赖,所以原型模式下会抛出异常。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
/**
* Return whether the specified prototype bean is currently in creation
* (within the current thread).
* @param beanName the name of the bean
* 判断当前正在加载的bean是否是原型,如果是原型就返回true
*/
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
//prototypesCurrentlyInCreation是一个ThreadLocal,所以获取到的是当前线程的私有数据,这个ThreadLocal中
//是一个set,里面包含了当前正在创建的原型类
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
/** Names of beans that are currently in creation */
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");
检测方式和单例的检查方式一样,用一个集合保存所有正在加载的bean的名字,然后在这个集合中查找有没有这个beanname。不同的是单例使用的是一个set,原型使用的是ThreadLocal。
//4.如果容器中没有找到就从父类容器中加载
BeanFactory parentBeanFactory = getParentBeanFactory();
//这里有个问题,什么时候,beanname是不会在BeanDefinition里面的呢
//这里应该是指不在自己的BeanDefinitionMap里但是在父类的里面
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//验证方法注入
//确定原始beanName,如果去掉了前缀就把前缀给加回来
String nameToLookup = originalBeanName(name);
//父类若为AbstractBeanFactory,那么委托父类进行加载
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);
}
}
这里我不是很懂,为什么beanName会不存在于BeanDefinition中,或者说什么情况下会执行到委托父类进行加载这里来呢。
但是对于本代码来说,containsBeanDefinition(beanName)返回false的时候,就会调用父类的getBean方法进行加载。程序的逻辑比较简单,但是最终都是调用父类的getBean方法来加载。
protected String originalBeanName(String name) {
String beanName = transformedBeanName(name);
if (name.startsWith(FACTORY_BEAN_PREFIX)) {
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}
transformedBeanName方法就是doGetBean方法一开始执行的那个方法,它去除了FactoryBean的前缀,处理了别名。
在originalBeanName的方法中,我们将被去除的前缀&又加了回去,然后返回。
这里要理清一个逻辑,就是&的作用是干嘛的
比如在我的实例当中,
是这样声明的,通过调试,这个FactoryBean的beanname是car。我们通过传入getBean("car")表示我们想获取到这个FactoryBean创造的类,但是我们如果用getBean("&car"),那么就代表我们想获得这个FactoryBean的实例。 这两个方向的逻辑处理在getObjectForBeanInstance方法中完成的。
所以我们在向上委托父类的时候,一定要将name恢复到原状。
//6.从容器中获取beanname对应的 GenericBeanDefinition 对象,
// 并将其转换为 RootBeanDefinition 对象,转换的原因是RootBeanDefinition提供了更多的方法供之后使用
//这里提到的合并BeanDefinition指的是将beanName对应的子类的BeanDefinition
//与同为子类的RootBeanDefinition的属性融合,得到RootBeanDefinition。可以理解为类型转换一下
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查给定的合并的BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
//快速从缓存中获取
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
//缓存中没有再调用getMergedBeanDefinition,进行合并
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException {
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}
检查获取到得RootBeanDefinition。
如果A DependsOn B,那么处理化A之前一定会先初始B。这就是解决DependsOn依赖。
//7.处理所依赖的bean
//注意这里的依赖指的并不是循环依赖里面的那个依赖,这个说的应该是@dependsOn这个属性,用来
//指定Bean加载的顺序的
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 {
//递归处理依赖bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}这里的代码逻辑比较绕,我们先理解一下等一下要用到的两个Map
/** Map between dependent bean names: bean name --> Set of dependent bean names */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
比如A DependsOn B 和 C
那么第一个集合中保存 B —>(A) C---->(A)
第二个集合中保存 A ---->(B,C)
然后接着往下看
// DefaultSingletonBeanRegistry.java
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;
}
这个代码挺绕的,不过使用一个实例调试一下就会清楚很多。
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取 beanName
String canonicalName = canonicalName(beanName);
// 添加 > 到 dependentBeanMap 中
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
// 添加 > 到 dependenciesForBeanMap 中
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
到了这里为了解释清楚这里解决依赖的逻辑和检测循环依赖,可以举一个例子。
比如这里有一个A -->B ,然后B—>A.
开始isDependent(A,B)必定返回false,然后到了registerDependentBean中,注册为
dependentBeanMap:B—>(A)
dependenciesForBeanMap:A—>(B)
然后就调用getBean创建B去了。B也会执行上面的流程
在isDependent(B,A)中
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
这个语句就会成立,就会返回true,然后就会抛出异常。这是比较简单的一种情况。