Spring学習のソース分析--D e f a ultSingletonBeanRegistry
DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistryクラスはSimpleAliasRegistryを継承し、SingletonBeanRegistryを実現するインタフェースを継承します.Beanの登録、破棄、および依存関係の登録と破棄を処理します.
クラス構造
切り取り部分
フィールド
メソッド解析
registerSingleton
beanの名前とオブジェクトで登録します.
addSingleton
キャッシュに単一のインスタンスを追加
addSingletonFactory
getSingleton
onSuppressedException
登録中に発生した例外を例外セットに追加
removeSingleton
単一のインスタンスを削除します.この4つは同時に削除されます.
containsSingleton
getSingletonNames
getSingletonCount
singletonObjects、registeredSingletonsの情報読み出し
setCurrentlyInCreation
チェックしないbeanNameの設定
isCurrentlyInCreation
isActuallyInCreation
isSingletonCurrentlyInCreation
現在作成されているbean
beforeSingletonCreation
afterSingletonCreation
registerDisposableBean
使い捨てbeanインスタンスの登録
registerContainedBean
registerDependentBean
canonicalNameメソッドはSimpleAliasRegistryに属するメソッドです.
isDependent
dependentBeanNameがbeanNameに依存しているかどうか
hasDependentBean
他のオブジェクト依存指定beanがあるかどうか
getDependentBeans
指定したbeanに依存する配列を返す
getDependenciesForBean
指定したbeanを返し、他のbeanに依存する配列を返します.
destroySingletons
廃棄ケース
clearSingletonCache
シングル・キャッシュのパージ
destroySingleton
単例beanの破棄
destroyBean
消費bean
getSingletonMutex
ロック操作に使用してsingletonObjectsを返し、このオブジェクトをメソッドで露出します.
DefaultSingletonBeanRegistryクラスはSimpleAliasRegistryを継承し、SingletonBeanRegistryを実現するインタフェースを継承します.Beanの登録、破棄、および依存関係の登録と破棄を処理します.
クラス構造
切り取り部分
フィールド
// : beanname bean
private final Map singletonObjects = new ConcurrentHashMap<>(256);
// : beanname ObjectFactory
private final Map> singletonFactories = new HashMap<>(16);
// : beanname bean
private final Map earlySingletonObjects = new HashMap<>(16);
// , beanname
private final Set registeredSingletons = new LinkedHashSet<>(256);
// beanName
private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// bean
private final Set inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//
private Set suppressedExceptions;
// bean
private boolean singletonsCurrentlyInDestruction = false;
// bean
private final Map disposableBeans = new LinkedHashMap<>();
// bean bean
private final Map> containedBeanMap = new ConcurrentHashMap<>(16);
// bean bean , bcd a, key a,bcd value
private final Map> dependentBeanMap = new ConcurrentHashMap<>(64);
// bean bean , a bcd, key a,bcd value
private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
メソッド解析
registerSingleton
beanの名前とオブジェクトで登録します.
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(beanName, singletonObject);
}
}
addSingleton
キャッシュに単一のインスタンスを追加
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//
this.singletonObjects.put(beanName, singletonObject);
// , singletonFactories earlySingletonObjects
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
// bean
this.registeredSingletons.add(beanName);
}
}
addSingletonFactory
// , getObject
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);
}
}
}
getSingleton
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {//
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);// ,
if (singletonObject == null && allowEarlyReference) {//allowEarlyReference singletonFactories
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {// , getObject
singletonObject = singletonFactory.getObject();
// singletonFactories earlySingletonObjects
this.earlySingletonObjects.put(beanName, singletonObject);
// , , earlySingletonObjects
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
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) {
// bean,
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 {
// ObjectFactory getObject 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.
// bean
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) {
// bean, , bean, ,
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
onSuppressedException
登録中に発生した例外を例外セットに追加
protected void onSuppressedException(Exception ex) {
synchronized (this.singletonObjects) {
if (this.suppressedExceptions != null) {
this.suppressedExceptions.add(ex);
}
}
}
removeSingleton
単一のインスタンスを削除します.この4つは同時に削除されます.
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
containsSingleton
getSingletonNames
getSingletonCount
singletonObjects、registeredSingletonsの情報読み出し
@Override
public boolean containsSingleton(String beanName) {
//
return this.singletonObjects.containsKey(beanName);
}
@Override
public String[] getSingletonNames() {
// bean
synchronized (this.singletonObjects) {
return StringUtils.toStringArray(this.registeredSingletons);
}
}
@Override
public int getSingletonCount() {
//
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
setCurrentlyInCreation
チェックしないbeanNameの設定
public void setCurrentlyInCreation(String beanName, boolean inCreation) {
Assert.notNull(beanName, "Bean name must not be null");
if (!inCreation) {
this.inCreationCheckExclusions.add(beanName);
}
else {
this.inCreationCheckExclusions.remove(beanName);
}
}
isCurrentlyInCreation
isActuallyInCreation
isSingletonCurrentlyInCreation
現在作成されているbean
public boolean isCurrentlyInCreation(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
// beanName , false,
// beanName , bean
return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
}
protected boolean isActuallyInCreation(String beanName) {
return isSingletonCurrentlyInCreation(beanName);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
beforeSingletonCreation
afterSingletonCreation
protected void beforeSingletonCreation(String beanName) {
// beanName , add , false, ,
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
// beanName , remove , false, 。
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
registerDisposableBean
使い捨てbeanインスタンスの登録
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}
registerContainedBean
public void registerContainedBean(String containedBeanName, String containingBeanName) {
synchronized (this.containedBeanMap) {
// key containingBeanName value, bean ,
Set containedBeans =
this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8));
// , , ,
if (!containedBeans.add(containedBeanName)) {
return;
}
}
registerDependentBean(containedBeanName, containingBeanName);
}
registerDependentBean
canonicalNameメソッドはSimpleAliasRegistryに属するメソッドです.
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
// , , ,
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
//
dependenciesForBean.add(canonicalName);
}
}
isDependent
dependentBeanNameがbeanNameに依存しているかどうか
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set dependentBeans = this.dependentBeanMap.get(canonicalName);
// , bean beanName, false
if (dependentBeans == null) {
return false;
}
// bean beanName, dependentBeanName, true
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
// bean beanName, dependentBeanName
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
//
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
hasDependentBean
他のオブジェクト依存指定beanがあるかどうか
protected boolean hasDependentBean(String beanName) {
return this.dependentBeanMap.containsKey(beanName);
}
getDependentBeans
指定したbeanに依存する配列を返す
public String[] getDependentBeans(String beanName) {
Set dependentBeans = this.dependentBeanMap.get(beanName);
if (dependentBeans == null) {
return new String[0];
}
synchronized (this.dependentBeanMap) {
return StringUtils.toStringArray(dependentBeans);
}
}
getDependenciesForBean
指定したbeanを返し、他のbeanに依存する配列を返します.
public String[] getDependenciesForBean(String beanName) {
Set dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
if (dependenciesForBean == null) {
return new String[0];
}
synchronized (this.dependenciesForBeanMap) {
return StringUtils.toStringArray(dependenciesForBean);
}
}
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());
}
// disposableBeans bean
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
// containedBeanMap、dependentBeanMap、dependenciesForBeanMap
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
//
clearSingletonCache();
}
clearSingletonCache
シングル・キャッシュのパージ
protected void clearSingletonCache() {
synchronized (this.singletonObjects) {
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
// , false
this.singletonsCurrentlyInDestruction = false;
}
}
destroySingleton
単例beanの破棄
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
//
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
// disposableBeans , beanName ,
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
// bean
destroyBean(beanName, disposableBean);
}
destroyBean
消費bean
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// Trigger destruction of dependent beans first...
Set dependencies;
// beanName bean
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
// beanName bean
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isTraceEnabled()) {
logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
// beanName bean
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
}
// Actually destroy the bean now...
if (bean != null) {
try {
// bean
bean.destroy();
}
catch (Throwable ex) {
if (logger.isInfoEnabled()) {
logger.info("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
}
}
}
// Trigger destruction of contained beans...
// beanName bean
Set containedBeans;
synchronized (this.containedBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);
}
}
// Remove destroyed bean from other beans' dependencies.
// bean ,
synchronized (this.dependentBeanMap) {
for (Iterator>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry> entry = it.next();
Set dependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
// beanName, ,
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
}
// Remove destroyed bean's prepared dependency information.
// bean bean
this.dependenciesForBeanMap.remove(beanName);
}
getSingletonMutex
ロック操作に使用してsingletonObjectsを返し、このオブジェクトをメソッドで露出します.
public final Object getSingletonMutex() {
return this.singletonObjects;
}