8-Spring容器創建之refresh(2)——【prepareRefresh】與【ConfigurableListableBeanFactory】

上一篇:Spring容器創建之refresh(1)——概覽

上一篇介紹了refresh方法的概覽,其中包含12個方法,接下來我們就依照順序依次聊一下每個方法所實現的功能以及如何實現的。這篇文章先介紹【prepareRefresh】與【ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()】。

1. prepareRefresh方法

	protected void prepareRefresh() {
		// 記錄容器啓動的事件.
		this.startupDate = System.currentTimeMillis();
		// 設置對應的標誌位
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// 擴展方法:本文使用的是AnnotationConfigApplicationContext進行創建容器因此在這裏這個方法爲空實現
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		// 這裏我沒有用到,所以暫時也沒有具體看是做什麼的,後續再補充吧!
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

這個方法也比較簡單。

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 刷新容器  2.1節介紹
		refreshBeanFactory();
		// 返回beanFactory  2.2節介紹
		return getBeanFactory();
	}

2.1 refreshBeanFactory()

	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}

這個方法就實現一個功能:爲beanFactory設置一個序列化Id

2.2 getBeanFactory()

	public final ConfigurableListableBeanFactory getBeanFactory() {
		return this.beanFactory;
	}

這裏爲什麼還要在refresh裏面再獲取一下beanFactory呢? 答案有點繞,

回顧一下在第一篇文章:Spring容器創建之this()(1)——AnnotatedBeanDefinitionReader中,我們在this()裏面,由於AnnotationConfigApplicationContext類的父類是GenericApplicationContext類,因此在有參構造器中調用this()時,首先執行父類GenericApplicationContext類的構造器,然後
再執行GenericApplicationContext類的父類AbstractBeanFactory的構造器。其中在調用GenericApplicationContext類的構造器的時候,執行的是:

	private final DefaultListableBeanFactory beanFactory;
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

而在本篇文章2.1節中 refresh方法所在的類爲:AbstractApplicationContext,他是GenericApplicationContext的父類,因此無法獲取GenericApplicationContext中的beanFactory,我們只能再調用refreshBeanFactory方法使得AbstractApplicationContext擁有beanFactory。爲了方便理解AbstractApplicationContextGenericApplicationContextAnnotationConfigApplicationContext之間的關係,下面給出類圖
在這裏插入圖片描述

3. 總結

  1. prepareRefresh方法:刷新前的預處理工作
  2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory():將this()方法中創建的beanFactory暴露給refresh方法所在的AbstractApplicaitonContext類,這樣該類中refresh方法裏的其他方法纔可以使用beanFactory
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章