Spring 概念模型 -- 单例bean注册表缺省实现 DefaultSingletonBeanRegistry

基于 Spring 5.1.3 RELEASE 分析

概述

DefaultSingletonBeanRegistrySpring各种bean容器的基类。
Spring单例bean注册表抽象建模接口SingletonBeanRegistry的缺省实现。具体来讲,DefaultSingletonBeanRegistry具备以下功能 :

  1. SingletonBeanRegistry接口约定的单例bean注册表功能;
  2. 继承自SimpleAliasRegistry,从而具备接口AliasRegistry定义的bean别名管理功能;
  3. 管理单例bean之间依赖关系(dependency)的功能;
  4. 管理单例bean之间包含关系(containment)的功能;
  5. 管理Disposable单例bean的功能;
  6. 标记/获取一个单例bean是否正处于创建过程中的功能;
  7. 销毁所管理的单例bean和各种关系的功能;

源代码解析

属性定义

Map缓存已经创建完成的单例bean实例

  • key : bean名称
  • value : 单例bean实例

这里创建完成表示 : 对象创建,属性设置,依赖注入,初始化及初始化前置后置处理都已经完成

	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

Map缓存单例bean实例的创建工厂ObjectFactory

  • key :bean名称
  • value :单例bean实例创建工厂ObjectFactory
	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

Map缓存及早暴露的单例bean实例

  • key : bean名称
  • value : 及早暴露的单例bean实例

这里及早暴露的单例bean实例指的是那些创建尚未完成单例bean实例 :

  • 对象创建已经完成,
  • 属性设置/依赖注入尚未完成,初始化及初始化前置后置处理尚未开始

该数据结构主要用于处理单例bean之间的循环依赖。

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

Set缓存所注册的单例bean的名称集合

添加顺序是这些bean的注册顺序。

	/** Set of registered singletons, containing the bean names in registration order. */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

Set缓存创建中的单例bean名称

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

当前是否处于销毁阶段标志

指出目前我们是否处于正在销毁单例bean实例阶段,缺省值为 false

	/** Flag that indicates whether we're currently within destroySingletons. */
	private boolean singletonsCurrentlyInDestruction = false;

Map缓存Disposable单例bean实例

用于缓存那些实现了接口Disposable的单例bean实例 : Map

  • key : bean 名称
  • value : 实现了接口Disposable的单例bean实例
	/** Disposable bean instances: bean name to disposable instance. */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

缓存单例bean之间的包含关系

缓存单例bean的从属方: Map

  • key : 单例bean名称,表示包含关系中的包含者
  • value : 被包含的那些单例bean的名称集合
	/** Map between containing bean names: bean name to Set of bean names that the 
	bean contains. */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

Map缓存单例bean之间的依赖关系

Map缓存从属关系

缓存单例bean的从属方: Map

  • key : 单例bean名称,表示依赖关系中的被依赖方
  • value : 从属于key对应单例bean的那些单例bean的名称集合

这里缓存的从属方是直接从属方,如果两个bean之间存在间接从属关系,这种间接从属关系并不保存在该数据结构中,而是需要通过计算获得。

举例来讲,如果beanB的一个属性是beanA,则beanAkey被依赖方,beanB则是value依赖方(从属方)的一员。

	/** Map between dependent bean names: bean name to Set of dependent bean names. */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

Map缓存依赖关系

缓存单例bean的依赖方: Map

  • key : 单例bean名称,表示依赖关系中的从属方
  • value : 被依赖的单例bean的名称的集合,是key对应的单例bean所依赖的那些单例bean的名称的集合。

这里缓存的依赖方是直接依赖方,如果两个bean之间存在间接依赖关系,这种间接依赖关系并不保存在该数据结构中,而是需要通过计算获得。

举例来讲,如果beanB的一个属性是beanA,则beanBkey从属方,beanA则是value被依赖方的一员。

	/** Map between depending bean names: bean name to Set of bean names for the bean's
	 dependencies. */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

直接依赖和直接从属是两个bean之间同一"关系"从不同角度来看而存在的概念,如果B直接从属于A,也就意味着AB的直接依赖方。

其他辅助属性

检测单例bean当前是否创建中时使用的一个集合,该集合中的bean名称需要从创建检查中忽略。

	/** Names of beans currently excluded from in creation checks. */
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	/** List of suppressed Exceptions, available for associating related causes. */
	@Nullable
	private Set<Exception> suppressedExceptions;

功能方法

SingletonBeanRegistry接口约定的单例bean注册表功能

注册单例bean实例

供使用者,通常是实现子类(也就是Spring的容器实现),在外部创建好对象之后将其注册为指定名称的单例bean

	@Override
	public void registerSingleton(String beanName, Object singletonObject) 
		throws IllegalStateException {
		Assert.notNull(beanName, "Bean name must not be null");
		Assert.notNull(singletonObject, "Singleton object must not be null");
		synchronized (this.singletonObjects) {
			Object oldObject = this.singletonObjects.get(beanName);		
			if (oldObject != null) {
			// 如果已经注册过则不能再次注册
				throw new IllegalStateException("Could not register object [" + 
				singletonObject +
				"] under bean name '" + beanName + "': there is already object [" + 
				oldObject + "] bound");
			}
			// 如果没有注册过才允许注册,通过#addSingleton方法完成注册
			addSingleton(beanName, singletonObject);
		}
	}

#addSingleton方法将一个bean对象作为一个单例正式注册,使用指定名称beanName,所做的动作有 :

  1. 添加singletonObjectsingletonObjects
  2. 如果该beanNamesingletonFactories有对应的项则删除
  3. 如果该beanNameearlySingletonObjects有对应的项则删除
  4. 添加beanNameregisteredSingletons
	/**
	 * Add the given singleton object to the singleton cache of this factory.
	 * To be called for eager registration of singletons.
	 * @param beanName the name of the bean
	 * @param singletonObject the singleton object
	 */
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

注册单例bean实例创建工厂ObjectFactory

	/**
	 * Add the given singleton factory for building the specified singleton
	 * if necessary.
	 * To be called for eager registration of singletons, e.g. to be able to
	 * resolve circular references.
	 * @param beanName the name of the bean
	 * @param singletonFactory the factory for the singleton object
	 */
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

获取指定名称的单例bean实例:允许创建及早暴露实例

此方法主要供使用者获取已经外部注册进来的单例bean,或者已经通过getSingleton(String beanName, ObjectFactory singletonFactory)创建的单例bean

@Override
	@Nullable
	public Object getSingleton(String beanName) {
		// allowEarlyReference 使用 true,表示允许创建及早暴露实例,
		// allowEarlyReference 主要用于解决循环依赖
		return getSingleton(beanName, true);
	}
	/**
	 * Return the (raw) singleton object registered under the given name.
	 * Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference 是否允许创建及早暴露引用,true--允许,false--不允许
	 * @return 所注册的单例对象。如果没有找到,返回null。
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 从缓存singletonObjects查找指定名字的单例bean对象到singletonObject
		Object singletonObject = this.singletonObjects.get(beanName);
		// singletonObject为null表示没有找到
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			// 如果没有找到,并且指定名称的bean正在创建过程中,则
			// 1. 如果对应单例bean对象已经存在于earlySingletonObjects则直接返回
			// 2. 如果对应单例bean对象不存在于earlySingletonObjects,并且允许
			//    创建及早暴露引用,也就是allowEarlyReference == true,则尝试
			//    获取该bean对应的对象创建工厂ObjectFactory创建相应的单例bean
			//    对象并记录到earlySingletonObjects,同时也从singletonFactories
			//    移除相应的对象创建工厂ObjectFactory(因为对象已经创建)。
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

上面protected Object getSingleton(String beanName, boolean allowEarlyReference)方法的执行流程如下 :

其他
没找到但正在创建过程中
其他
没找到但允许创建及早暴露实例
开始
从singletonObjects查找目标单例对象
返回查找结果(也可能是null)
从earlySingletonObjects查找目标单例对象
返回null
从singletonFactories获取实例创建工厂
实例创建工厂存在?
使用实例创建工厂创建及早暴露实例
将及早暴露实例缓存到earlySingletonObjects
从singletonFactories删除该bean的实例创建工厂
返回及早暴露实例
	/**
	 * Return the (raw) singleton object registered under the given name,
	 * creating and registering a new one if none registered yet.
	 * @param beanName the name of the bean
	 * @param singletonFactory the ObjectFactory to lazily create the singleton
	 * with, if necessary
	 * @return the registered singleton object
	 */
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			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 + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					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;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

是否包含指定名称的单例bean

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

获取所有单例bean的名称

	@Override
	public String[] getSingletonNames() {
		synchronized (this.singletonObjects) {
			return StringUtils.toStringArray(this.registeredSingletons);
		}
	}

获取所有单例bean的数量

	@Override
	public int getSingletonCount() {
		synchronized (this.singletonObjects) {
			return this.registeredSingletons.size();
		}
	}

获取单例注册表互斥量

该方法暴露一个单例注册表的操作互斥量给子类和外部调用者协调操作单例注册表。子类如果在单例实例创建过程中有任何扩展逻辑,要操作单例注册表时应该同步该互斥量。尤其需要注意的是,子类在一个单例创建时不应该再使用其它自己的互斥量以免延迟初始化时发生死锁。

	/**
	 * Exposes the singleton mutex to subclasses and external collaborators.
	 * Subclasses should synchronize on the given Object if they perform
	 * any sort of extended singleton creation phase. In particular, subclasses
	 * should not have their own mutexes involved in singleton creation,
	 * to avoid the potential for deadlocks in lazy-init situations.
	 */
	public final Object getSingletonMutex() {
		return this.singletonObjects;
	}

注意此方法被设定为final,子类不能覆盖,原因是所要协调访问的资源singletonObjects在本类提供实现并对外界和子类封装为不可见。

单例bean依赖关系管理功能

#registerDependentBean

	/**
	 * Register a dependent bean for the given bean,
	 * to be destroyed before the given bean is destroyed.
	 * @param beanName the name of the bean 被依赖方
	 * @param dependentBeanName the name of the dependent bean 依赖方,从属者
	 */
	public void registerDependentBean(String beanName, String dependentBeanName) {
		// 标准化被依赖方bean名称
		String canonicalName = canonicalName(beanName);

		// 将被依赖方dependentBeanName添加为依赖方beanName的一个从属 :
		// 1. 从被依赖方的角度处理:添加一个从属
		synchronized (this.dependentBeanMap) {
			Set<String> dependentBeans =
					this.dependentBeanMap.computeIfAbsent(canonicalName, 
					k -> new LinkedHashSet<>(8));
			if (!dependentBeans.add(dependentBeanName)) {
				return;
			}
		}

		// 2. 从从属方的角度处理 : 添加一个依赖
		synchronized (this.dependenciesForBeanMap) {
			Set<String> dependenciesForBean =
					this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, 
					k -> new LinkedHashSet<>(8));
			dependenciesForBean.add(canonicalName);
		}
	}

#getDependentBeans

	/**
	 * Return the names of all beans which depend on the specified bean, if any.
	 * @param beanName the name of the bean
	 * @return the array of dependent bean names, or an empty array if none
	 */
	public String[] getDependentBeans(String beanName) {
		Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
		if (dependentBeans == null) {
			return new String[0];
		}
		synchronized (this.dependentBeanMap) {
			return StringUtils.toStringArray(dependentBeans);
		}
	}

#getDependenciesForBean

	/**
	 * Return the names of all beans that the specified bean depends on, if any.
	 * @param beanName the name of the bean
	 * @return the array of names of beans which the bean depends on,
	 * or an empty array if none
	 */
	public String[] getDependenciesForBean(String beanName) {
		Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
		if (dependenciesForBean == null) {
			return new String[0];
		}
		synchronized (this.dependenciesForBeanMap) {
			return StringUtils.toStringArray(dependenciesForBean);
		}
	}

#isDependent 从属关系判断

这里包含直接从属关系和间接从属关系的判断。

/**
	 * Determine whether the specified dependent bean has been registered as
	 * dependent on the given bean or on any of its transitive dependencies.
	 * @param beanName the name of the bean to check
	 * @param dependentBeanName the name of the dependent bean
	 * @since 4.0
	 */
	protected boolean isDependent(String beanName, String dependentBeanName) {
		synchronized (this.dependentBeanMap) {
			return isDependent(beanName, dependentBeanName, null);
		}
	}

	private boolean isDependent(String beanName, String dependentBeanName, 
		@Nullable Set<String> alreadySeen) {
		if (alreadySeen != null && alreadySeen.contains(beanName)) {
			return false;
		}
		String canonicalName = canonicalName(beanName);
		Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
		if (dependentBeans == null) {
			return false;
		}
		if (dependentBeans.contains(dependentBeanName)) {
			return true;
		}
		for (String transitiveDependency : dependentBeans) {
			if (alreadySeen == null) {
				alreadySeen = new HashSet<>();
			}
			alreadySeen.add(beanName);
			if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
				return true;
			}
		}
		return false;
	}

#hasDependentBean 判断某个单例是否被依赖

	/**
	 * Determine whether a dependent bean has been registered for the given name.
	 * @param beanName the name of the bean to check
	 */
	protected boolean hasDependentBean(String beanName) {
		return this.dependentBeanMap.containsKey(beanName);
	}	

单例bean包含关系管理功能

#registerContainedBean

	/**
	 * Register a containment relationship between two beans,
	 * e.g. between an inner bean and its containing outer bean.
	 * Also registers the containing bean as dependent on the contained bean
	 * in terms of destruction order.
	 * @param containedBeanName the name of the contained (inner) bean
	 * @param containingBeanName the name of the containing (outer) bean
	 * @see #registerDependentBean
	 */
	public void registerContainedBean(String containedBeanName, String containingBeanName) {
		synchronized (this.containedBeanMap) {
			Set<String> containedBeans =
					this.containedBeanMap.computeIfAbsent(containingBeanName, 
					k -> new LinkedHashSet<>(8));
			if (!containedBeans.add(containedBeanName)) {
				return;
			}
		}
		// 包含关系同时也意味着依赖关系,所以使用方法#registerDependentBean进行注册:
		// 包含者containingBeanName 依赖于 被包含者containedBeanName
		registerDependentBean(containedBeanName, containingBeanName);
	}

管理disposable单例bean的功能

#registerDisposableBean

注册DisposableBean到指定的bean名称。DisposableBean通常和所注册的单例bean实例对应,使用同样的bean名称,但可能是不同的实例。比如某个单例bean实例对应的可能是一个DisposableBean适配器,该适配器并不实现Spring接口DisposableBean

	/**
	 * Add the given bean to the list of disposable beans in this registry.
	 * Disposable beans usually correspond to registered singletons,
	 * matching the bean name but potentially being a different instance
	 * (for example, a DisposableBean adapter for a singleton that does not
	 * naturally implement Spring's DisposableBean interface).
	 * @param beanName the name of the bean
	 * @param bean the bean instance
	 */
	public void registerDisposableBean(String beanName, DisposableBean bean) {
		synchronized (this.disposableBeans) {
			this.disposableBeans.put(beanName, bean);
		}
	}

标记/获取一个单例bean是否需要被创建检查排除掉

#setCurrentlyInCreation:标记一个单例bean是否需要被创建检查排除掉

	// inCreation 表示正在创建中
	public void setCurrentlyInCreation(String beanName, boolean inCreation) {
		Assert.notNull(beanName, "Bean name must not be null");
		if (!inCreation) {
			// !inCreation 表示不在创建中 => 需要被创建检查排除掉
			this.inCreationCheckExclusions.add(beanName);
		}
		else {
			// inCreation 表示正在创建中 => 创建检查需要检查该bean
			this.inCreationCheckExclusions.remove(beanName);
		}
	}

#isCurrentlyInCreation:获取一个单例bean是否需要被创建检查排除掉

	// 检测某个bean当前是否正在被创建
	public boolean isCurrentlyInCreation(String beanName) {
		Assert.notNull(beanName, "Bean name must not be null");
		// inCreationCheckExclusions不包含指定bean 并且
		// 指定bean真正在创建过程中, 则认为它当前正在被创建
		return (!this.inCreationCheckExclusions.contains(beanName) && 
			isActuallyInCreation(beanName));
	}

	// 检测指定bean是否在真正的创建过程中
	protected boolean isActuallyInCreation(String beanName) {
		// 如果singletonsCurrentlyInCreation包含beanName,说明
		// 指定bean在真正的创建过程中
		return isSingletonCurrentlyInCreation(beanName);
	}

	/**
	 * Return whether the specified singleton bean is currently in creation
	 * (within the entire factory).
	 * @param beanName the name of the bean
	 */
	public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

销毁所有单例bean及其之间的关系

#destroySingletons

	public void destroySingletons() {
		if (logger.isTraceEnabled()) {
			logger.trace("Destroying singletons in " + this);
		}
		synchronized (this.singletonObjects) {
			this.singletonsCurrentlyInDestruction = true;
		}

		String[] disposableBeanNames;
		synchronized (this.disposableBeans) {
			disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
		}
		for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
			destroySingleton(disposableBeanNames[i]);
		}

		this.containedBeanMap.clear();
		this.dependentBeanMap.clear();
		this.dependenciesForBeanMap.clear();

		clearSingletonCache();
	}

	/**
	 * Clear all cached singleton instances in this registry.
	 * @since 4.3.15
	 */
	protected void clearSingletonCache() {
		synchronized (this.singletonObjects) {
			this.singletonObjects.clear();
			this.singletonFactories.clear();
			this.earlySingletonObjects.clear();
			this.registeredSingletons.clear();
			this.singletonsCurrentlyInDestruction = false;
		}
	}

你可能感兴趣的:(Spring,Core)