前言
上篇文章我們對注冊 Bean 的核心類 BeanDefinitionRegistry 進行了討論,這里的注冊 Bean 是指保存 Bean 的相關信息,也就是將 Bean 定義成 BeanDefinition,然后放入容器中。除此之外,Spring 還提供一個統一操作單例 Bean 實例的類 SingletonBeanRegistry,通過該類可直接對單例 Bean 的實例進行存儲、注冊等操作。
SingletonBeanRegistry
SingletonBeanRegistry 是一個接口,其定義了操作單例 Bean 實例的一些基礎方法:
public interface SingletonBeanRegistry {
// 注冊單例 Bean。其實就是將該 Bean 保存到一個專門存儲單例 Bean 實例的Map中,Key是 beanName,Value是對應的單例 Bean 實例
void registerSingleton(String beanName, Object singletonObject);
// 通過 beanName 獲取該單例 Bean 實例
Object getSingleton(String beanName);
// 通過 beanName 判斷該單例 Bean 實例是否存在
boolean containsSingleton(String beanName);
// 返回所有單例 Bean 的名稱
String[] getSingletonNames();
// 返回已注冊的單例 Bean 實例數量
int getSingletonCount();
// 返回當前使用的單例鎖,主要提供給外部協作者使用
Object getSingletonMutex();
}
這個接口的核心實現類是 DefaultSingletonBeanRegistry,該類不僅實現了這些基礎方法,還針對單例 Bean 擴展了許多功能,如:存儲 Bean 之間的依賴關系、存儲 Bean 的包含關系(外部類包含內部類)、獲取 Bean 所處的狀態(正在創建、創建完畢等)、回調銷毀 Bean 時觸發的 destroy 方法等。
下面是 DefaultSingletonBeanRegistry 類中的核心屬性和方法:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/********** 1、定義的一些 Map 屬性,用來保存單例 Bean 實例、 Bean 的依賴關系 **********/
// 緩存單例 Bean 實例,Key 是 beanName,Value 是單例 Bean 實例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 緩存 Bean 對應的 ObjectFactory
// ObjectFactory 是獲取 Bean 實例的工廠,只不過這里獲取的 Bean 還未完全實例化,屬於提早暴露的 Bean
// 該屬性在解決循環依賴時使用,后續會深入討論
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 緩存 singletonFactories 屬性中通過 ObjectFactory 創建的 Bean
// 該屬性也是在解決循環依賴時使用,后續會深入討論
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 保存已注冊的單例 Bean 名稱
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
// 保存當前正在創建的 Bean 的名稱
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 保存當前從創建檢查中排除的 Bean 的名稱
private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
...
// 當前 Bean 是否處於銷毀狀態
private boolean singletonsCurrentlyInDestruction = false;
// 保存實現了 DisposableBean 接口的 Bean,在銷毀 Bean 時,會回調該 Bean 中的 destory 方法
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
// 保存 Bean 的包含關系,key 是 Bean 的名稱,value 是 Bean 里面包含的其它 Bean 名稱集合
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
// 保存 Bean 的依賴關系:key 是 Bean 的名稱,value 是依賴於該 Bean 的其它 Bean 名稱集合
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
// 保存 Bean 的依賴關系:key 是 Bean 的名稱,value 是該 Bean 所依賴的其它 Bean 名稱集合
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
/******************************** 2、注冊單例 Bean 實例及對應的實例工廠 ********************************/
// 注冊單例 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) {
// 通過 beanName 獲取 Map 中對應的單例 Bean 實例
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);
}
}
// 緩存單例 Bean 實例
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 將單例 Bean 實例存放至 singletonObjects 集合
this.singletonObjects.put(beanName, singletonObject);
// 當 beanName 對應的 Bean 實例已被存放至 singletonObjects 集合時,singletonFactories
// 和 earlySingletonObjects 集合則不能再持有 beanName 對應的 ObjectFactory 和實例
// 其中原因會在后續循環依賴的文章深入討論
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
// 存儲 Bean 名稱
this.registeredSingletons.add(beanName);
}
}
// 緩存 Bean 對應的 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 實例 *********************************/
@Override
public Object getSingleton(String beanName) {
// 該方法較為復雜,在后續結合循環依賴的場景討論
}
...
/***************************** 4、對單例 Bean 實例的基礎操作 *****************************/
// 刪除單例 Bean 實例
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 對應的單例 Bean 實例時候存在
@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 實例數量
@Override
public int getSingletonCount() {
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
...
/*************************************** 5、 Bean 的狀態 **************************************/
// beanName 對應的 Bean 是否處於實例化階段
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 實例化前執行,將正要創建的 Bean 加入 singletonsCurrentlyInCreation 集合
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
// 單例 Bean 實例化后執行,從 singletonsCurrentlyInCreation 集合中移除已創建的 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、 存儲 Bean 之間的關系、判斷 Bean 之間的關系 *********************/
// 保存具有包含關系的 Bean(內部類與外部類)
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);
}
// 保存具有依賴關系的 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 類中的屬性及方法雖然很多,但也有規律可循的,大致分為對單例 Bean 實例的操作、管理 Bean 之間關系、針對 Bean 的不同狀態進行操作及銷毀 Bean 的操作。
該類中的核心還是那些 Map,類中的所有方法都是對這些 Map 進行操作,而這些 Map 中存儲的是不同場景下的單例 Bean 。
最后
關於 SingletonBeanRegistry 就介紹到這,其主要還是針對單例 Bean 進行操作,外部調用者統一繼承該類操作單例 Bean,其主要調用者還是 DefaultListableBeanFactory,前篇文章也說過,這是我們當前上下文環境中使用的 BeanFactory 工廠類,在工廠類中執行 getBean 操作時,會調用這些方法,后續會詳細討論 getBean 操作。最后值得注意是,Spring 也是在該類中解決循環依賴問題,這部分也會在后面詳細討論。