spring源码:bean加载之获取单例(getSingleton()方法)

一、介绍

  从spring容器中获取单例时有两种情况:缓存中存在缓存中不存在。缓存中不存在的情况,需要调用getSingleton()方法来获取单例。本章主要介绍获取单例的整体流程,该逻辑中创建bean的步骤较为复杂,放在后面章节单独介绍。

二、bean加载流程
  1. 获取用户传入name对应的beanName
  2. 尝试从缓存中获取bean实例
  3. 缓存中不存在,加载bean实例
    3.1. 检查循环依赖
    3.2 处理parentBeanFactory
    3.3 处理依赖的bean(dependsOn)
    3.4 三种bean实例的创建
     3.4.1 单例bean的创建
      3.4.1.1 获取单例bean,getSingleton()方法(本章解析
      3.4.1.2 创建bean,createBean()方法
     3.4.2 原型bean的创建
     3.4.3 根据scope策略创建bean
  4. 从bean实例中获取真正的对象
  5. 转换对象类型
  6. 返回对象实例
三、相关类及方法
  • org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean:加载一个Bean的整体过程都在这个方法中
  • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>):获取单例
  • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingleton:把单例bean存入缓存
四、源码分析

1. 先看加载bean的方法,AbstractBeanFactory#doGetBean

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
				@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		// 1.转换beanName,主要处理别名、以&开头的name
		final String beanName = transformedBeanName(name);
		Object bean;
	
		// 2.尝试从单例缓存中获取bean实例
		Object sharedInstance = getSingleton(beanName);
		// 3. 获取bean实例
		// 3.1 缓存中已存在bean实例
		if (sharedInstance != null && args == null) {
			// 省略日志输出代码...
			// 从bean实例中获取对象(本章重点,获取实例中的对象)
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		// 缓存中不存在bean实例的情况
		else {
			// 省略父工厂处理相关代码...
			try {
				// 省略dependsOn相关代码...

				// 3.2 创建单例bean
				if (mbd.isSingleton()) {
					// 获取单例(本章重点)
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// 3.3 创建原型bean实例
				else if (mbd.isPrototype()) {
				// 省略原型bean创建逻辑...
				}
				// 3.4 根据scope创建bean实例
				else {
					// 省略根据scope策略创建bean逻辑...
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}
		// 省略其他代码.
		...
	}

可以看到缓存中不存在bean实例时,创建单例bean的逻辑是调用getSingleton()方法完成的,跟进去看下具体逻辑。

2. 获取单例的整体逻辑

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		// 同步代码块
		synchronized (this.singletonObjects) {
			// 1. 再次尝试从缓存中获取bean实例
			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. 创建单例的前置处理,把该beanName置为创建中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 3. 通过入参ObjectFactory创建bean(该方法逻辑较为复杂,后面章节单独讲述)
					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. 创建单例的后置处理
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					// 5. 把创建的单例加入到缓存
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

3. 创建单例的前置处理

	// 保存正在创建中状态的beanName
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
			
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

把该beanName加入到DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation,表明该bean正在创建中。

4. 把创建好的单例加入到缓存

	// 单例对象缓存: bean name --> bean instance
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	// 按注册顺序排列的bean名称列表
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
	
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			// 缓存单例对象
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			// 记录已注册beanName
			this.registeredSingletons.add(beanName);
		}
	}

5. 创建单例的后置处理

	protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}

把该beanName从DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation中移除,表明该bean已创建完成。

五、总结
  • 从源码分析中看到,容器中已加载的单例bean对象已注册的beanName保存在DefaultSingletonBeanRegistry类中
// bean对象缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 已注册beanName
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
  • 获取单例逻辑可以总结为以下五个步骤
  1. 再次尝试从缓存中获取bean实例
  2. 创建单例的前置处理
  3. 通过入参ObjectFactory创建bean
  4. 创建单例的后置处理
  5. 把创建的单例加入到缓存
    后面我们就单独讲下第3个步骤:通过入参ObjectFactory创建bean
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值