上一篇介紹了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
。爲了方便理解AbstractApplicationContext
、GenericApplicationContext
和AnnotationConfigApplicationContext
之間的關係,下面給出類圖
3. 總結
prepareRefresh
方法:刷新前的預處理工作ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
:將this()
方法中創建的beanFactory
暴露給refresh
方法所在的AbstractApplicaitonContext
類,這樣該類中refresh
方法裏的其他方法纔可以使用beanFactory
。