spring学习(四)——Bean的加载(从缓存获取单例 Bean)

参考文章:

http://www.iocoder.cn

bean的加载流程

从缓存中获得单例的bean的代码位于org/springframework/beans/factory/support/AbstractBeanFactory.java的方法doGetBean

代码片段

// 从缓存中或者实例工厂中获取 Bean 对象
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			//完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

 

深入查看内部逻辑发现【getSingleton】是其获得对象的关键,spring获得bean的Instance后通过getObjectForBeanInstance获得最终的bean

而其内部代码片段

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 从单例中加载bean
		Object singletonObject = this.singletonObjects.get(beanName);
		// 类为空,且类正在创建中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//加锁
			synchronized (this.singletonObjects) {
				//从早期bean中获取
				singletonObject = this.earlySingletonObjects.get(beanName);
				// earlySingletonObjects 中没有,且允许提前创建
				if (singletonObject == null && allowEarlyReference) {
					// 获得bean的创建工厂
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//创建bean
						singletonObject = singletonFactory.getObject();
						//将bean放入早期map中
						this.earlySingletonObjects.put(beanName, singletonObject);
						//从创建工厂中移除此工厂
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

 

从上面代码可以发现几个关键内容

  • this.singletonObjects.get(beanName) 获得单例的对象
  • 假如不存在则从this.earlySingletonObjects.get(beanName)获得单例对象
  • 假如还没有则从this.singletonFactories.get(beanName);中获得创建工厂

这上面singletonObjects,earlySingletonObjects,singletonFactories是spring类创建的三个map其含义为

	/**
	 * 存放的是单例 bean 的映射。
	 * 对应关系为 bean name --> bean instance
	 */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/**
	 * 存放的是 ObjectFactory 的映射,可以理解为创建单例 bean 的 factory 。
	 * 对应关系是 bean name --> ObjectFactory
	 */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/**
	 * 存放的是【早期】的单例 bean 的映射。
	 * 对应关系也是 bean name --> bean instance。
	 * 它与 {@link #singletonObjects} 的区别区别在,于 earlySingletonObjects 中存放的 bean 不一定是完整的。
	 * 从 {@link #getSingleton(String)} 方法中,中我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了,
	 * 所以当在 bean 的创建过程中就可以通过 getBean() 方法获取。
	 * 用来解决循环依赖
	 */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

而除了从几个map中获得值以外,还有几个重要的方法

isSingletonCurrentlyInCreation 判断类是否在创建中

此方法就是从map中获得值进行比对,对应的代码为

public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

	/** Names of beans that are currently in creation. */
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

 

getObjectForBeanInstance

从缓存中蝴蝶beanInstance后下面就要通过getObjectForBeanInstance还获得最终的bean了

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// 若为工厂类引用(name 以 & 开头)
		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			// 如果是 NullBean,则直接返回
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			// 如果不是工厂类
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}

		// 到这里我们就有了一个 Bean 实例,当然该实例可能是会是是一个正常的 bean 又或者是一个 FactoryBean
		// 如果是 FactoryBean,我我们则创建该 Bean
		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		//如果bean为空,则从bean的缓存中获得beanInstance
		if (mbd == null) {
			object = getCachedObjectForFactoryBean(beanName);
		}
		// 如果bean依然为空,则从bean的工厂中取出bean
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			//检测是否定义 beanName
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				// 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,
				// 如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			// 是否是用户定义的,而不是应用程序本身定义的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 核心处理方法,使用 FactoryBean 获得 Bean 对象
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

 

以上代码可以看到两种情况

  • 第一种,当该实例对象为非 FactoryBean 类型直接返回给定的 Bean 实例对象 beanInstance 。
  • 第二种,当该实例对象为FactoryBean 类型,从 FactoryBean ( beanInstance ) 中,获取 Bean 实例对象。

代码的大致流程

  • 首先从factoryBeanObjectCache 获得bean:getCachedObjectForFactoryBean(beanName)
  • 假如不存在则使用使用 FactoryBean 获得 Bean 对象:getObjectFromFactoryBean(factory, beanName, !synthetic)

所以关键方法是bean:getCachedObjectForFactoryBean、getObjectFromFactoryBean

我们首先来看getCachedObjectForFactoryBean:

他是直接从一个factoryBeanObjectCache的map集合中根据key获取value的,代码如下:

	@Nullable
	protected Object getCachedObjectForFactoryBean(String beanName) {
		return this.factoryBeanObjectCache.get(beanName);
	}

	/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
	private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

然后我们来看getObjectFromFactoryBean

假如换从中不存在,spring需要创建beanFactory

首先我们看spring会从几个map中验证beanName,代码如下

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		// 为单例模式且缓存中存在
		if (factory.isSingleton() && containsSingleton(beanName)) {
			// 加锁
			// 获取锁。其实我们在前面篇幅中发现了大量的同步锁,
			// 锁住的对象都是 this.singletonObjects,主要是因为在单例模式中必须要保证全局唯一
			synchronized (getSingletonMutex()) {
				//从缓存中获取指定的 factoryBean
				Object object = this.factoryBeanObjectCache.get(beanName);
				// 如果不存在bean
				if (object == null) {
					// 则从 FactoryBean 中获取对象
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)

					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					// 缓存中不存在bean
					else {
						//需要后续处理
						if (shouldPostProcess) {
							//若该 Bean 处于创建中,则返回非处理对象,而不是存储它
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							//单例 Bean 的前置处理
							beforeSingletonCreation(beanName);
							try {
								// 对从 FactoryBean 获取的对象进行后处理
								// 生成的对象将暴露给 bean 引用
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								//单例 Bean 的后置处理getSingleton
								afterSingletonCreation(beanName);
							}
						}
						//添加到 factoryBeanObjectCache 中,进行缓存
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
			// 缓存中不存在
			// 则从 FactoryBean 中获取对象
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					// 对从 FactoryBean 获取的对象进行后处理
					// 生成的对象将暴露给 bean 引用
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

 

//为单例模式且缓存中存在
if (factory.isSingleton() && containsSingleton(beanName))

@Override
	public boolean containsSingleton(String beanName) {
		return this.singletonObjects.containsKey(beanName);
	}

/**
	 * 存放的是单例 bean 的映射。
	 * 对应关系为 bean name --> bean instance
	 */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

验证单例缓存中是否存在

//从缓存中获取指定的 factoryBean
				Object object = this.factoryBeanObjectCache.get(beanName);

	/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
	private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

验证bean的缓存中是否存在

 

假如缓存中不存在则从doGetObjectFromFactoryBean中获取

object = doGetObjectFromFactoryBean(factory, beanName);

 

然后添加引用关系postProcessObjectFromFactoryBean

object = postProcessObjectFromFactoryBean(object, beanName);

而假如缓存中不存在或者非单例模式则直接执行doGetObjectFromFactoryBean、postProcessObjectFromFactoryBean方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值