Spring IOC 从单例池中获取Bean

本文详细介绍了Spring IOC在获取Bean时如何处理FactoryBean,特别是从单例池中获取Bean的流程,包括getSingleton方法、isSingletonCurrentlyInCreation的使用,以及getObjectForBeanInstance和getObjectFromFactoryBean的逻辑。文章还探讨了循环依赖解决的关键步骤和相关缓存策略。
摘要由CSDN通过智能技术生成

概述

在doGetBean方法当中,处理完bename之后,下一步就是尝试从单例池中获取。如果能获取到,那么就对其进行FactoryBean的处理。当然这个处理对于FactoryBean才有用,对应代码如下:

		// Eagerly check singleton cache for manually registered singletons.
		//如果这里是我们的bean,那么第一次获取肯定是空的,那么这个时候就会走else
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
   
			if (logger.isDebugEnabled()) {
   
				if (isSingletonCurrentlyInCreation(beanName)) {
   
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
   
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			//2.完成FactoryBean的相关处理,并用来获取FactoryBean的处理结果。
			//缓存中的bean记录的是最原始的Bean状态,我们得到的不一定是最终想要的bean
			//
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
  • 这个if选项如果是我们第一次调用这个方法来获取,那么必定通过getSingleton方法返回的对象是空的。那么我们将会进入到else流程中,执行创建Bean的流程。
  • 获取到Bean之后,由于FactoryBean的存储方式和普通Bean是一样的,如果这个Bean是FactoryBean的话,要对器进行处理,得到真正的Bean。

getSingleton

	//传入的第二个参数就是指是否允许延迟加载
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   
		//第一次调用getSongleton,返回肯定为空
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
   
			synchronized (this.singletonObjects) {
   
				//从三级缓存拿,如果是第一次坑定是拿不到的
				singletonObject = this.earlySingletonObjects.get(beanName);
				//如果从三级缓存中拿不到,那么判断是否支持循环依赖,再从二级缓存中拿
				/**
				 * 为什么不直接从二级缓存中拿,而是要put到三级缓存中呢
				 * 性能问题:因为二级缓存是一个工厂,代码相当复杂。从二级缓存中创建出对象的时候进行大量的操作
				 * 为了避免每次引用这个对象都要使用工厂来创建,就需要使用到三级缓存。
				 * 既然有性能消耗,那么为什么还要使用工厂呢?
				 * 解答:因为在前面说过spring的生命周期:
				 * 1.new
				 * 2.注入
				 * 3.执行生命周期方法
				 * 4.AOP代理
				 * 5.放入单例池
				 * 还是循环依赖的场景。如果此时A到了注入的那一步,那么就会进入到B的生命周期。如果这个地方我们不使用工厂
				 * 那么在B中注入的A就是只执行到第二步的一个A的对象。B的A就不是AOP代理过后的对象。为了解决这个问题使用工厂,因为
				 * 它可以使这个A的AOP操作提前到这个工厂中来执行。所以说这个工厂的代码也是极其复杂的。为了避免重复执行这里面
				 * 的代码,这里也用到了三级缓存的。
				 */
				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);
					}
				}
			}
		}
		retur
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值