基于
Spring 5.1.3 RELEASE
分析
DefaultSingletonBeanRegistry
是Spring
各种bean
容器的基类。
是Spring
单例bean
注册表抽象建模接口SingletonBeanRegistry
的缺省实现。具体来讲,DefaultSingletonBeanRegistry
具备以下功能 :
SingletonBeanRegistry
接口约定的单例bean
注册表功能;SimpleAliasRegistry
,从而具备接口AliasRegistry
定义的bean
别名管理功能;bean
之间依赖关系(dependency
)的功能;bean
之间包含关系(containment
)的功能;Disposable
单例bean
的功能;bean
是否正处于创建过程中的功能;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
,则beanA
是key
被依赖方,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
,则beanB
是key
从属方,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
,也就意味着A
是B
的直接依赖方。
检测单例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
,所做的动作有 :
singletonObject
到 singletonObjects
beanName
在singletonFactories
有对应的项则删除beanName
在earlySingletonObjects
有对应的项则删除beanName
到 registeredSingletons
/**
* 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)
方法的执行流程如下 :
/**
* 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;
}
}