Spring IOC容器生命周期
- BeanFactory和ApplicationContext有何區別?
- 原始碼展示
- 1. Spring應用背景關系啟動準備階段
- 2. BeanFactory創建階段
- 3. BeanFactory初始化階段
- 4. BeanFactory后置處理階段
- 5. BeanFactory注冊BeanPostProcessor階段
- 6. 初始化國際化
- 7. 初始化應用事件廣播器
- 8. Spring應用背景關系重繪階段
- 9. Spring注冊監聽器階段
- 10. BeanFactory初始化完成階段
- 11. Spring應用背景關系啟動完成階段
- 12. Spring應用背景關系啟動階段
- 13. Spring應用背景關系停止階段:
- 14. Spring應用背景關系關閉階段:
BeanFactory和ApplicationContext有何區別?
到底什么才是Spring容器呢?我們需要分清楚以上兩個類的區別,
● ApplicationContext是BeanFactory的子介面
● BeanFactory是一個底層的IOC容器,提供了IOC容器的基本實作,而ApplicationContext則是BeanFactory的超集提供了豐富的企業級特性,
● ApplicationContext是委托DefaultListableBeanFactory來實作Bean的依賴查找和依賴注入,
接下來就詳細介紹一下Spring容器的完整生命周期都做了哪些事情,
首先,入口是AbstractApplicationContext.refresh()方法其實是啟動容器,這是一個抽象類,許多的應用背景關系都實作了這個類,比如最常見的:
org.springframework.context.support.ClassPathXmlApplicationContext
接下來看下源代碼中是長什么樣子,
原始碼展示
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
其中的階段做的事情非常之多,閱讀時難免會陷入某一個階段中去,而無法做到對全域做一個把握,這里就是分解一下各個階段所做的事情,從而對有一個全域的視角,Spring的體系比較龐雜,我們只能各個擊破,
1. Spring應用背景關系啟動準備階段
AbstractApplicationContext#prepareRefresh();
該方法為容器啟動做準備
a. 啟動時間
b. 容器狀態標識
c. 初始化PropertySources-->initPropertySources()空方法留給子類實作
d. 檢驗Environment中的必須屬性
e. 初始化事件監聽集合
f. 初始化早期Spring事件集合
2. BeanFactory創建階段
AbstractApplicationContext#obtainFreshBeanFactory();
通過模板方法模式在子類中實作容器的獲取結果是DefaultListableBeanFactory,
Tips: 大多數應用背景關系的實作都繼承了AbstractRefreshableApplicationContext,
a. 重繪Spring應用背景關系底層
BeanFactoryAbstractRefreshableApplicationContext#refreshBeanFactory()
i. 銷毀或關閉BeanFactory,如果已經存在的話,
ii. 創建BeanFactory:createBeanFactory()
iii. 設定BeanFactory Id
iv. 設定“是否允許BeanDefinition重復定義”
v. 設定“是否允許回圈依賴”
vi. 加載BeanDefinition:loadBeanDefinitions(DefaultListableBeanFactory)
vii. 關聯新建BeanFactory到Spring應用背景關系
b. 回傳Spring應用背景關系底層BeanFactory=>getBeanFactory()
3. BeanFactory初始化階段
AbstractApplicationContext#prepareBeanFactory()
a. 關聯classloader
b. 設定Bean運算式處理器(SpringEL相關的內容)
c. 添加PropertyEditorRegistrar實作:ResourceEditorRegistrar
d. 添加Aware回呼介面BeanPostProcessor實作:ApplicationContextAwareProcessor
e. 添加Aware回呼介面作為依賴注入介面
f. 注冊ResolvableDependency內建的非Bean物件:BeanFactory、ResourceLoader、ApplicationEventPublisher以及ApplicationContext
g. 注冊ApplicationListenerDetector物件
i. 對于符合ApplicationListener介面且是單例的Bean記錄到singletonsName,后面會作為ApplicationListener關聯到ApplicationContext中,
h. 注冊LoadTimeWeaverAwareProcessor物件(AOP相關)
i. 注冊單例物件:Environment、Java System Properties以及OS環境變數
4. BeanFactory后置處理階段
針對容器的擴展
a. postProcessBeanFactory(beanFactory)
i. 是個空方法,需要子類去擴展這個方法
b. InvokeBeanFactoryPostProcessors(beanFactory)
i. 迭代所有BeanFactoryPostProcessor判斷它是否是BeanDefinitionRegistryPostProcessor型別
1. 如果是則執行其postProcessBeanDefinitionRegistry方法,并在registryProcessors集合中加入當前迭代物件BeanFactoryPostProcessor,
2. 否則直接加入regularPostProcessors集合中,表示是常規的PostProcessor,
ii. Spring容器中的BeanFactoryPostProcessor有可能實作了PriorityOrdered、Ordered介面,也可能沒有實作,對他們進行分別歸類之后按照PriorityOrdered、Ordered、常規的BeanFactoryPostProcessor的集合順序去執行,
iii. 分別遍歷處理registryProcessors和regularpostProcessors兩個集合物件,執行迭代物件的postProcessBeanFactory方法,因為其實集合的物件都實作了BeanFactoryPostProcessor介面,
5. BeanFactory注冊BeanPostProcessor階段
AbstractApplicationContext#registerBeanPostProcessors(beanFactory);// 針對Bean的擴展
i. 注冊PriorityOrdered型別的BeanPostProcessor Beans
ii. 注冊Ordered型別的BeanPostProcessor Beans
iii. 注冊普通的BeanPostProcessor Beans
iv. 注冊MergedBeanDefinitionPostProcessor Beans
v. 注冊ApplicationListenerDetector物件
6. 初始化國際化
initMessageSource()
● 在Spring容器中依賴查找MessageSource并根據情況設定其層次性
● 如果IOC容器中沒有則創建一個DelegatingMessageSource并設定其層次性,然后在Spring容器中注冊MessageSource單例物件
7. 初始化應用事件廣播器
AbstractApplicationContext#initApplicationEventMulticaster()
a. 在Spring容器中判斷并依賴查找ApplicationEventMulticaster物件,并賦值給當前容器的applicationEventMulticaster
b. 如果IOC容器中沒有則創建一個SimpleApplicationEventMulticaster,然后在Spring容器中注冊ApplicationEventMulticaster單例物件,
8. Spring應用背景關系重繪階段
初始化特殊Bean->onRefresh()
這個方法是一個空實作,提供給子類擴展,比如StaticWebApplicationContext、AbstractRefreshableWebApplicationContext子類則是提供了關于theme主題的實作,
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
9. Spring注冊監聽器階段
AbstractApplicationContext#registerListeners()
a. 添加當前應用背景關系所關聯的ApplicationListener集合物件
b. 添加BeanFactory所注冊ApplicationListener Beans
c. 廣播早期Spring事件
10. BeanFactory初始化完成階段
AbstractApplicationContext#finishBeanFactoryInitialization(beanFactory)
a. BeanFactory關聯ConversionService Bean(如果存在的話)
b. 添加StringValueResolver物件提供處理占位符操作
c. 依賴查找LoadTimeWeaverAware Bean
d. BeanFactory臨時ClassLoader置為null
e. BeanFactory凍結配置
f. BeanFactory初始化非延遲單例Beans:beanFactory#preInstantiateSingletons()
11. Spring應用背景關系啟動完成階段
AbstractApplicationContext#finishRefresh()
a. 清除ResourceLoader快取:clearResourceCaches()
b. 初始化LifecycleProcessor物件:initLifecycleProcessor()
c. 呼叫LifecycleProcessor#onReFresh())方法
d. 發布Spring應用背景關系已重繪事件:ContextRefreshedEvent
e. 向MBeanServer托管LiveBeans(可以通過jconsole查看)
12. Spring應用背景關系啟動階段
AbstractApplicationContext#start()
a. 這個方法一般起輔助作用,可以不呼叫它,,
b. 作用一:啟動LifecycleProcessor
c. 作用二:發布Spring應用背景關系已啟動事件:ContextStartedEvent事件
13. Spring應用背景關系停止階段:
AbstractApplicationContext#stop()
a. 跟start方法一樣是輔助作用,
b. 作用一:停止LifecycleProcessor
c. 作用二:發布Spring應用背景關系已停止事件:ContextStoppedEvent事件
14. Spring應用背景關系關閉階段:
AbstractApplicationContext#close()
a. Spring容器設定狀態標識:active=false,closed=true
b. Live Beans JMX撤銷托管
c. 發布Spring應用背景關系的已關閉事件
d. 關閉LifecycleProcessor
e. 銷毀Spring Beans
f. 關閉BeanFactory
g. 回呼onClose()
h. 如果ShutdownHook這個執行緒不為null,remove ShutDown Hook Thread
其中start和stop方法用的很少,它們只是起到一個輔助IOC容器的作用,對了解IOC容器的整個生命周期不是非常重要,重點關注refresh方法即可,
CSDN認證博客專家
Java
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/251670.html
標籤:AI
