前言
上篇文章我們對(duì)注冊(cè) Bean 的核心類 BeanDefinitionRegistry 進(jìn)行了討論,這里的注冊(cè) Bean 是指保存 Bean 的相關(guān)信息,也就是將 Bean 定義成 BeanDefinition杂彭,然后放入容器中。除此之外茬故,Spring 還提供一個(gè)統(tǒng)一操作單例 Bean 實(shí)例的類 SingletonBeanRegistry盖灸,通過該類可直接對(duì)單例 Bean 的實(shí)例進(jìn)行存儲(chǔ)、注冊(cè)等操作磺芭。
SingletonBeanRegistry
SingletonBeanRegistry 是一個(gè)接口赁炎,其定義了操作單例 Bean 實(shí)例的一些基礎(chǔ)方法:
public interface SingletonBeanRegistry {
// 注冊(cè)單例 Bean。其實(shí)就是將該 Bean 保存到一個(gè)專門存儲(chǔ)單例 Bean 實(shí)例的Map中,Key是 beanName徙垫,Value是對(duì)應(yīng)的單例 Bean 實(shí)例
void registerSingleton(String beanName, Object singletonObject);
// 通過 beanName 獲取該單例 Bean 實(shí)例
Object getSingleton(String beanName);
// 通過 beanName 判斷該單例 Bean 實(shí)例是否存在
boolean containsSingleton(String beanName);
// 返回所有單例 Bean 的名稱
String[] getSingletonNames();
// 返回已注冊(cè)的單例 Bean 實(shí)例數(shù)量
int getSingletonCount();
// 返回當(dāng)前使用的單例鎖讥裤,主要提供給外部協(xié)作者使用
Object getSingletonMutex();
}
這個(gè)接口的核心實(shí)現(xiàn)類是 DefaultSingletonBeanRegistry,該類不僅實(shí)現(xiàn)了這些基礎(chǔ)方法姻报,還針對(duì)單例 Bean 擴(kuò)展了許多功能己英,如:存儲(chǔ) Bean 之間的依賴關(guān)系胯杭、存儲(chǔ) Bean 的包含關(guān)系(外部類包含內(nèi)部類)上遥、獲取 Bean 所處的狀態(tài)(正在創(chuàng)建峦萎、創(chuàng)建完畢等)藕漱、回調(diào)銷毀 Bean 時(shí)觸發(fā)的 destroy 方法等糯景。
下面是 DefaultSingletonBeanRegistry 類中的核心屬性和方法:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/********** 1世剖、定義的一些 Map 屬性逃糟,用來保存單例 Bean 實(shí)例捷绑、 Bean 的依賴關(guān)系 **********/
// 緩存單例 Bean 實(shí)例笆焰,Key 是 beanName劫谅,Value 是單例 Bean 實(shí)例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 緩存 Bean 對(duì)應(yīng)的 ObjectFactory
// ObjectFactory 是獲取 Bean 實(shí)例的工廠,只不過這里獲取的 Bean 還未完全實(shí)例化嚷掠,屬于提早暴露的 Bean
// 該屬性在解決循環(huán)依賴時(shí)使用捏检,后續(xù)會(huì)深入討論
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 緩存 singletonFactories 屬性中通過 ObjectFactory 創(chuàng)建的 Bean
// 該屬性也是在解決循環(huán)依賴時(shí)使用,后續(xù)會(huì)深入討論
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 保存已注冊(cè)的單例 Bean 名稱
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
// 保存當(dāng)前正在創(chuàng)建的 Bean 的名稱
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 保存當(dāng)前從創(chuàng)建檢查中排除的 Bean 的名稱
private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
...
// 當(dāng)前 Bean 是否處于銷毀狀態(tài)
private boolean singletonsCurrentlyInDestruction = false;
// 保存實(shí)現(xiàn)了 DisposableBean 接口的 Bean不皆,在銷毀 Bean 時(shí)贯城,會(huì)回調(diào)該 Bean 中的 destory 方法
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
// 保存 Bean 的包含關(guān)系,key 是 Bean 的名稱霹娄,value 是 Bean 里面包含的其它 Bean 名稱集合
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
// 保存 Bean 的依賴關(guān)系:key 是 Bean 的名稱冤狡,value 是依賴于該 Bean 的其它 Bean 名稱集合
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
// 保存 Bean 的依賴關(guān)系:key 是 Bean 的名稱,value 是該 Bean 所依賴的其它 Bean 名稱集合
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
/******************************** 2项棠、注冊(cè)單例 Bean 實(shí)例及對(duì)應(yīng)的實(shí)例工廠 ********************************/
// 注冊(cè)單例 Bean 實(shí)例
@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) {
// 通過 beanName 獲取 Map 中對(duì)應(yīng)的單例 Bean 實(shí)例
Object oldObject = this.singletonObjects.get(beanName);
// 如果不為空悲雳,則拋出異常,因?yàn)閱卫呀?jīng)存在香追,無法再次注冊(cè)
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
// 為空合瓢,則進(jìn)入 addSingleton 方法
addSingleton(beanName, singletonObject);
}
}
// 緩存單例 Bean 實(shí)例
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 將單例 Bean 實(shí)例存放至 singletonObjects 集合
this.singletonObjects.put(beanName, singletonObject);
// 當(dāng) beanName 對(duì)應(yīng)的 Bean 實(shí)例已被存放至 singletonObjects 集合時(shí),singletonFactories
// 和 earlySingletonObjects 集合則不能再持有 beanName 對(duì)應(yīng)的 ObjectFactory 和實(shí)例
// 其中原因會(huì)在后續(xù)循環(huán)依賴的文章深入討論
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
// 存儲(chǔ) Bean 名稱
this.registeredSingletons.add(beanName);
}
}
// 緩存 Bean 對(duì)應(yīng)的 ObjectFactory
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);
}
}
}
/********************************* 3透典、獲取單例 Bean 實(shí)例 *********************************/
@Override
public Object getSingleton(String beanName) {
// 該方法較為復(fù)雜晴楔,在后續(xù)結(jié)合循環(huán)依賴的場(chǎng)景討論
}
...
/***************************** 4、對(duì)單例 Bean 實(shí)例的基礎(chǔ)操作 *****************************/
// 刪除單例 Bean 實(shí)例
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
// 判斷 beanName 對(duì)應(yīng)的單例 Bean 實(shí)例時(shí)候存在
@Override
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
// 返回所有單例 Bean 的 beanName
@Override
public String[] getSingletonNames() {
synchronized (this.singletonObjects) {
return StringUtils.toStringArray(this.registeredSingletons);
}
}
// 返回單例 Bean 實(shí)例數(shù)量
@Override
public int getSingletonCount() {
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
...
/*************************************** 5峭咒、 Bean 的狀態(tài) **************************************/
// beanName 對(duì)應(yīng)的 Bean 是否處于實(shí)例化階段
public boolean isCurrentlyInCreation(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
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);
}
// 單例 Bean 實(shí)例化前執(zhí)行税弃,將正要?jiǎng)?chuàng)建的 Bean 加入 singletonsCurrentlyInCreation 集合
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
// 單例 Bean 實(shí)例化后執(zhí)行,從 singletonsCurrentlyInCreation 集合中移除已創(chuàng)建的 Bean
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
...
/********************* 6凑队、 存儲(chǔ) Bean 之間的關(guān)系则果、判斷 Bean 之間的關(guān)系 *********************/
// 保存具有包含關(guān)系的 Bean(內(nèi)部類與外部類)
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(containedBeanName, containingBeanName);
}
// 保存具有依賴關(guān)系的 Bean
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
...
/***************************** 7、 銷毀 Bean 的方法 *****************************/
...
}
DefaultSingletonBeanRegistry 類中的屬性及方法雖然很多,但也有規(guī)律可循的西壮,大致分為對(duì)單例 Bean 實(shí)例的操作遗增、管理 Bean 之間關(guān)系、針對(duì) Bean 的不同狀態(tài)進(jìn)行操作及銷毀 Bean 的操作款青。
該類中的核心還是那些 Map做修,類中的所有方法都是對(duì)這些 Map 進(jìn)行操作,而這些 Map 中存儲(chǔ)的是不同場(chǎng)景下的單例 Bean 抡草。
最后
關(guān)于 SingletonBeanRegistry 就介紹到這饰及,其主要還是針對(duì)單例 Bean 進(jìn)行操作,外部調(diào)用者統(tǒng)一繼承該類操作單例 Bean康震,其主要調(diào)用者還是 DefaultListableBeanFactory旋炒,前篇文章也說過,這是我們當(dāng)前上下文環(huán)境中使用的 BeanFactory 工廠類签杈,在工廠類中執(zhí)行 getBean 操作時(shí),會(huì)調(diào)用這些方法鼎兽,后續(xù)會(huì)詳細(xì)討論 getBean 操作答姥。最后值得注意是,Spring 也是在該類中解決循環(huán)依賴問題谚咬,這部分也會(huì)在后面詳細(xì)討論鹦付。