一、加載配置文件之後的各項操作流程
Spring的AbstractApplicationContext是ApplicationContext的抽象實現類,該類中的refresh()方法定義了spring容器在加載配置文件之後的各項操作流程,如下所示:
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
// 1.初始化beanFactory
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
// 2.調用工廠後處理器
this.invokeBeanFactoryPostProcessors(beanFactory);
// 3.註冊 bean後處理器
this.registerBeanPostProcessors(beanFactory);
// 4.初始化消息源
this.initMessageSource();
// 5.初始化應用上下文事件廣播器
this.initApplicationEventMulticaster();
// 6.初始化其他特殊的bean,由具體子類實現
this.onRefresh();
// 7.註冊事件監聽器
this.registerListeners();
// 8.初始化所有單實例的bean,使用懶加載模式的除外
this.finishBeanFactoryInitialization(beanFactory);
// 9.完成刷新併發布容器刷新事件
this.finishRefresh();
} catch (BeansException var9) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var9);
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
- 初始化BeanFactory:根據配置文件實例化BeanFactory,在obtainFreshBeanFactory()方法中,首先調用refreshBeanFactory()刷新,然後調用getBeanFactory()方法獲取beanFactory,這兩個方法都是由具體子類實現的。在這一步中,spring將配置文件裝入到容器的bean定義註冊表中(BeanDefinitionRegistry)中,但此時bean還未初始化
- 調用工廠後處理器:根據反射機制從BeanDefinitionRegistry中找出所有實現了BeanFactoryPostProcessor接口的bean,並調用其postProcessBeanFactory(ConfigurableListableBeanFactory var1)接口方法
- 註冊bean後處理器:根據反射機制從BeanDefinitionRegistry中找出所有實現了BeanPostProcessor接口的bean,並將他們註冊到容器bean後處理器的註冊表中
- 初始化消息源:初始化容器的國際化消息資源
- 初始化應用上下文事件廣播器
- 初始化其他特殊的bean:這是一個鉤子方法,子類可以藉助該方法實現一些特殊的操作。
- 註冊事件監聽器
- 初始化所有單實例的bean,使用懶加載模式的bean除外,初始化bean後,將他們放在spring容器的緩存池中
- 發佈上下文刷新事件,創建上下文刷新事件 ,事件廣播器負責將事件廣播到每個註冊的事件監聽器中
二、spring容器 從加載配置文件到創建一個完整的bean的流程如下所示:
-
ResourceLoader從存儲介質中加載spring的配置信息,並使用Resource來表示這個配置文件資源
-
BeanDefinitionReader讀取Resource所指向的配置資源,然後解析配置文件,配置文件的每個<bean>解析成一個BeanDefinition對象,並保存到BeanDefinitionRegistry中
- 容器掃描BeanDefinitionRegistry中的BeanDefinition,使用java反射機制自動識別出bean工廠後處理器(實現了實現了BeanFactoryPostProcessor接口的bean),然後調用這些工廠後處理器對BeanDefinition進行加工,主要完成一下兩項工作
- 對使用佔位符的<bean>元素標籤進行解析,得到最終的配置值,這意味着對一些半成品式的BeanDefinition對象進行加工並得到成品的BeanDefinition
- 對BeanDefinitionRegistry中的BeanDefinition進行掃描,通過java反射機制找出所有屬性編輯器的bean,(實現了java.beans.PropertyEditor接口的bean),並調用InstantiationStrategy着手進行bean實例化的工作
- 在實例化bean時,Spring容器使用BeanWrapper對Bean進行封裝。BeanWrapper提供了許多java反射操作 bean的方法,它將結合該 bean的BeanDefinition及容器中的屬性編輯器,完成bean屬性的注入操作
- 利用容器中註冊的Bean後處理器對已經完成屬性設置工作的Bean進行後續加工,直接裝配出一個準備就緒的bean