spring源码11: spring获取单例

目录

spring源码目录
git注释项目地址:https://github.com/chaitou/spring-framework-master.git


// AbstractBeanFactory.java
// 7. 单例情况下
if (mbd.isSingleton()) {
	/**
	 * 核心代码,spring4.x中是这么写的,会更容易理解一点
	 * sharedInstance = getSingleton(beanName, new ObjectFactory<object>() {
	 * 		getObject() {
	 * 			return createBean(beanName, mbd, args);
	 * 		}
	 * 	}
	 * 	即getSingleton第二个参数为ObjectFactory对象
	 */
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			// Explicitly remove instance from singleton cache: It might have been put there
			// eagerly by the creation process, to allow for circular reference resolution.
			// Also remove any beans that received a temporary reference to the bean.
			destroySingleton(beanName);
			throw ex;
		}
	});

	...
}

这里的写法可能有点绕,首先getSingleton传入2个参数,beanName和一个ObjectFactory对象。spring5.x以后使用了lambda表达式缩写,但是如代码注释,spring4.x的更为直观一些。新建一个ObjectFatory对象,其中ObjectFactory是一个接口,使用了匿名类去实现该接口,并且重写了getObject()方法


获取单例

// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		// 加个锁
		synchronized (this.singletonObjects) {
			// 1. 尝试从一级缓存中获取
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				// 2. 循环依赖检测的典型做法,如果发现当前bean需要被循环依赖检测且正在创建则抛出异常,否则标识当前的bean正在创建
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					/**
					 * 3. 回调singletonFactory的getObject方法,实际调用AbstractBeanFactory的createBean,而该方法又被子类所实现
					 * 所以实际调用的是AbstractAutowireCapableBeanFactory的createBean方法
					 */
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					// 4. 同样是循环依赖检测的典型做法,如果发现bean处于非创建状态则抛出异常,否则标识bean不在创建状态
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}
  1. 第一点还是惯用做法,先尝试从一级缓存获取,获取到则可以直接跳过创建

  1. 这点在前面章节介绍过,这里再回顾一下。在创建bean之前,需要先检查当前bean是否在创建列表中,如果在创建列表中说明存在循环引用,假设这里不抛出异常将会无限递归创建bean,造成死循环。该步骤对应的是下图的(1. 检测a是否在创建状态)。因为当前是单例模式,因此检测的集合是singletonsCurrentlyInCreation,而当原型模式下则使用propertysCurrentInCreation进行检测
	protected void beforeSingletonCreation(String beanName) {
		// 该beanName没有在排除检查列表中,且已经在创建中,则抛出循环依赖异常
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

循环依赖检测.jpg


  1. 调用刚刚传入的singletonObjects对象getObject()方法,这也是创建bean的核心逻辑。创建bean的过程包含了实例化、填充、初始化3大步骤以及多个后置处理器,因此我们单独拿出一节来讲解。详见:spring源码12: spring创建Bean
  2. 这一步对应上图的第10步,当bean正常创建完成时,记得将当前beanName移出正常创建的列表
	protected void afterSingletonCreation(String beanName) {
		// 当前beanName不在排除列表中,并且不在单例创建列表中
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值