浅谈 SpringBean的初始化之缓存中获取单例---主线逻辑 ( 二 )

    上一篇文章Spring Bean的初始化 主线逻辑 (一)主要简单的描述了getBean的大致流程。接下来 主要分析doGetBean中的重要方法。

     首先 对 Object sharedInstance = getSingleton(beanName) 进行分析:

    

@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 检查缓存中是否存在实例
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			// 如果为空并且循环创建 则锁定全局变量 处理
			synchronized (this.singletonObjects) {
				// 如果此bean 正在加载则不处理
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					 // 当某些方法需要提前初始化的时候 则会调用 addSingletonFactory 将其对应的
					 // ObjectFactory 初始化策略存储在 singletonFactories
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						// 调用预先设定的getObject 方法
						singletonObject = singletonFactory.getObject();
						// 记录在缓存中,earlySingletonObjects 和singletonFactories 是互斥的
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

    因为涉及到循环依赖的检测,所以设计很多变量记录的存取。其主要步骤:

 

     先从singletonObjects 缓存中获取,中获取不到再从earlySingletonObjects中获取,如果还是获取不到则从singletonFactories中获取beanName对应的ObjectFactory,然后调用ObjectFactory 的getObject 来创建bean,并加入到earlySingletonObjects中且从singletonFactories中remove,而对后续的内存操作只是为了解决循环依赖时使用,控制 flag 为 allowEarlyReference。

 在第一章中开头有让大家混个眼熟的几个map,现在 对他们的作用做一个介绍;

    1. singletonObjects : 用于保存 beanName 和创建实例的关系。

    2. earlySingletonObjects  : 也是保存beanName 和 instance实例之间的关系,但是 和 singletonObjects 不同之处在于,当一个单例bean放在这里后,那么当bean还在创建过程中就可以通过getBean 方法获取到了,其目的是检测循环引用的。

   3. singletonFactories :用于保存beanName 和创建Bean 工厂之间的关系。

  4. registeredSingletons: 用来保存当前已注册的Bean。

 

       接下来 分析  获取对应实例 方法( getObjectForBeanInstance(sharedInstance, name, beanName, null),

getObjectForBeanInstance  是一个高频方法。无论是从缓存中获取bean 还是 根据不同的scop策略加载bean,我们的到bean 后 需要做的第一件事就是检查bean的正确性。getObjectForBeanInstance   是用于当前bean是普通的bean还是factoryBean,如果是factoryBean 则需要调用factoryBean实例中的getObject。也就是说不管是从缓存中获取到的bean还是通过不同的scop构建的bean并不一定是用户真正想要的bean, 假如这个bean是factoryBean 我们得到只是这个工厂bean的初始状态,但是用户需要的是工厂bean中定义的 factory-method方法中返回的bean,getObjectForBeanInstance  就是干这个事的。

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName,
			@Nullable RootBeanDefinition mbd) {
		// 判断name是否是工厂相关(以&为前缀)
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			//如果指定的name是工厂相关且beanInstance又不是FactoryBean类型验证不通过
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
		}
		/**
		 * 一个bean 可以是 普通的bean 或者工厂bean(beanFactory)
		 */
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
		/**
		 *  获取由FactoryBean创建的bean实例
		 */
		Object object = null;
		if (mbd == null) {
			//  尝试从缓存中获取bean实例
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			// beanFactory类型 早已确认
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			// 如果指定beanName是子类的话同时会合并父类的相关属性
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			// 是否是用户定义的而不是应用程序本身定义的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

   步骤:

    setp1: 对factoryBean正确性验证

   step2: 对非FactoryBean 不做处理

   step3:合并属性,对bean转换

   step4:调用getObjectFromFactoryBean获取Bean

其中getObjectFromFactoryBean 中会判断 bean是不是单例,如果是单例则从缓存中去取。

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值