老生谈spring(二十):循环依赖(二)

老生谈spring(二十):循环依赖(二)

1、首先看doGetBean的方法,进来对name进行一个解析,如果是别名转换成beanName。然后二话不说,调用getSingleton方法去拿这个实例。
在这里插入图片描述2、getSingleton方法就是从三级缓存中去获取这个bean实例,首先从单例池singletonObjects中获取,获取不到则判断这个bean是否正在被创建,判断的依据就是singletonsCurrentlyInCreation容器里是否有这个beanName(创建bean前会把beanName放到singletonsCurrentlyInCreation)。如果是那么从earlySingletonObjects中获取这个bean,如果获取不到再从singletonFactories获取这个bean的工厂,如果能拿到这个工厂,那么就用这个工厂去创建bean,并且把创建的bean缓存到earlySingletonObjects中。

@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

	/**
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference whether early references should be created or not
	 * @return the registered singleton object, or {@code null} if none found
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

3、由于一开始这个bean是没有被创建的,它也没有bean工厂,所有getSingleton返回的是个null。由于返回的是null,所有第一个if就不进,进入的是else的代码。else的代码有个很明显的地方,就是判断这个bean的作用域是否是单例的。如果是那么调用重载的getSingleton方法,这个方法有两个参数,第一个是beanNmae,第二个传的是一个lambda表达式。可能有些人不是很熟悉lambda表达式,这里你简单认为传的就是一个匿名的bean工厂对象并且为它的getObject方法提供了实现,这个实现调用了createBean方法。
在这里插入图片描述
4、如果lambda表达式还么看懂那就先不管,我们来看重载的getSingleton方法。在getSingleton的方法里首先用synchronized保证现场安全,然后在beforeSingletonCreation这个方法把beanName存放到singletonsCurrentlyInCreation,表示这个bean正在被创建(呼应第2点)。然后使用singletonFactory的getObject方法去创建这个bean,而第3点中说过getObject的实现就是调用createBean方法。
在这里插入图片描述在这里插入图片描述
5、createBean方法的主要代码其实就是调了doCreateBean,这就是spring的代码风格,do开头的方法才是真正干活的。
在这里插入图片描述
6、doCreateBean我们也只看与循环依赖有关的代码,这里有个判断earlySingletonExposure是否为true,如果为true则提前暴露一个bean工厂。而earlySingletonExposure为true的满足条件就是这个bean是否是单例的,并且这个bean是否正在创建,并且allowCircularReferences是否为true。(现在你知道上一节中为什么把allowCircularReferences设置为false就不支持循环依赖了吧)

在这里插入图片描述
7、做完这件事后,就来到populateBean方法进行属性填充(依赖注入)。这个依赖注入的是一个bean的话也是调用到getBean方法,后面会详细讲解populateBean这个方法,这里就不作详细讲解了。假设创建A的bean执行到这里,就会去getBean创建B,而B又依赖注入了A,那么就会再次触发到A的getBean操作,而之所以不会陷入死循环就是因为在创建A对象提前暴露了A的工厂(三级缓存中的singletonFactories),所以这次getBean操作是能拿到一个半成品的A的bean,这时就能把这个半成品的bean注入到B中,在完成了B的生命周期后就能完成A中的B对象的注入。
在这里插入图片描述
8、由于这个过程非常绕,所以这里再描述一下这个步骤:
A 的getBean->提前暴露A的工厂->populateBean注入B->B的getBean->提前暴露B的工厂->populateBean注入A->A 的getBean->三级缓存中有A的工厂,用A的工厂创建这个bean->返回B的populateBean注入A->完成B的生命周期->返回A的populateBean注入B->完成A的生命周期

9、结语:思考两个问题:1、为什么三级缓存要缓存一个Bean的工厂?2、为什么要用三级缓存?二级不可以吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值