Spring(六)核心容器 - 注冊單例 Bean 實例、SingletonBeanRegistry 簡介


前言

上篇文章我們對注冊 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 也是在該類中解決循環依賴問題,這部分也會在后面詳細討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM