编程语言
首页 > 编程语言> > Spring源码 - 获取单例(上)

Spring源码 - 获取单例(上)

作者:互联网

Spring源码 - 获取单例(上)

Spring版本:Spring 5.3.13-release


# 1、doGetBean()创建Bean实例

AbstractBeanFactory#doGetBean()的源码中:

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object beanInstance;

		// 尝试从缓存中获取 Bean 实例对象
		Object sharedInstance = getSingleton(beanName);

		// 如果 Bean 的单例对象找到了, 并且没有创建实例时需要使用的参数
		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 + "'");
				}
			}

			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			
            // 源码篇幅过长,省略部分源码
			try {
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}

				// 源码篇幅过长,省略部分源码
				// 单实例 Bean 实例化
				if (mbd.isSingleton()) {

					// 返回以 beanName 的(原始)单例对象, 如果未注册, 则使用 SingletonFactory 创建并注册一个对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 为给定的合并后的 BeanDefinition 和创建该 Bean 所需的参数来创建一个 Bean 实例对象
							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.
							// 显示地从单例缓存中删除实例 : 它可能是由创建过程急切地放在那里, 以允许循环依赖解。
							// 还要移除接收到该 Bean 临时引用的任何 Bean
							destroySingleton(beanName);
							// 重新抛出异常
							throw ex;
						}
					});
					// 从 BeanInstance 中获取公开的 Bean 对象, 主要处理 BeanInstance 是 FactoryBean 的情况
					// 如果不是 FactoryBean 会直接返回 beanInstance 实例
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// 原型模式的创建
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					// 检查当前 Bean 是否是 FactoryBean<?> 类型的 Bean 实例
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				else {
					// 指定 Scope 上实例化 Bean
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
					}
					Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						// 检查当前 Bean 是否是 FactoryBean<?> 类型的 Bean 实例
						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
				beanCreation.end();
			}
		}
		// 对实例化的 Bean 实例进行类型转换
		return adaptBeanInstance(name, beanInstance, requiredType);
	}

doGetBean()方法的源码篇幅较长,总结下来Spring会优先尝试从缓存中获取Bean实例,如果未获取到则需要创建当前beanName对应的Bean实例。对于单实例Bean的加载,Spring则是将详细的加载过程委派给了DefaultSingletonBeanRegistry#getSingleton()方法。


# 2、getSingleton()加载Bean实例

DefaultSingletonBeanRegistry#getSingleton()重载方法源码:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		// 同步全局变量, 保证线程安全
		synchronized (this.singletonObjects) {
			// 这一步是非常有必要的, 否则可能会重复创建 Bean 实例
			Object singletonObject = this.singletonObjects.get(beanName);
			// 如果获取不到对象, 则进行 singleton 的初始化
			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 + "'");
				}

				// 创建单例之前的回调, 默认实现将单例注册为当前正在创建中, 便于循环依赖的检测
				beforeSingletonCreation(beanName);

				// 表示生成了新单例对象的标记, 默认为 false, 表示没有生成新的单例对象
				boolean newSingleton = false;
				// 有抑制异常记录标记, 没有时为 true, 否则为 false
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);

				// 如果没有抑制异常记录
				if (recordSuppressedExceptions) {
					// 对抑制的异常列表进行实例化
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 从单例工厂中获取对象, 调用在 AbstractBeanFactory 中传递进来的 ObjectFactory<T> 函数式接口
					singletonObject = singletonFactory.getObject();

					// 生成了新的单例对象标记为 true, 表示生成了新的单例对象
					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;
					}
					// 当 Bean 加载结束后需要移除缓存中对该 Bean 的正在加载状态的记录
					afterSingletonCreation(beanName);
				}
				// 如果是生成新的单例 Bean
				if (newSingleton) {
					// 加入一级缓存
					addSingleton(beanName, singletonObject);
				}
			}
			// 返回加载的 Bean 实例
			return singletonObject;
		}
	}

如果有不了解ObjectFactory<T>接口的可以查看这篇文章:Spring源码 - 核心接口ObjectFactory

需要注意,在调用ObjectFactory<?>接口中的getObject()方法其实质则是激活AbstractAutowireCapableBeanFactory#doCreateBean()方法中的createBean()方法。


# 3、createBean()创建Bean实例

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		// 锁定 class, 根据设置的 class 属性或者根据 className 来解析 class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		// 进行条件筛选, 重新赋值 RootBeanDefinition, 并设置 BeanClass 属性
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			// 重新创建一个 RootBeanDefinition 对象
			mbdToUse = new RootBeanDefinition(mbd);
			// 设置 BeanClass 属性
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		// 验证及准备覆盖的方法 : lookup-method, replace-method。当需要创建的 Bean 对象中包含了
		// lookup-method 和 replace-method 标签的时候, 会产生覆盖操作
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			// 给 BeanPostProcessors 一个机会来返回代理来替代正真的实例, 应用实例化前的前置处理器, 用户自定义动态代理的方式
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			// 实际创建 Bean 调用
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

在分析doCreateBean()方法源码之前还需了解Spring的循环依赖,请见Spring源码 - 获取单例(下)

GitHub源码地址https://github.com/kapbc/kapcb-spring-source/tree/master/Spring-Framework-v5.3.13

备注:此文为笔者学习Spring源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

更多Java技术笔记可扫码关注下方微信公众号。

目目沐沐微信公众号

标签:实例,mbd,Spring,beanName,bean,Bean,源码,ex,单例
来源: https://blog.csdn.net/qq_43911324/article/details/122642180