1.概述
簡(jiǎn)單來說IOC容器的初始化過程是通過refresh()
方法來啟動(dòng)的,這個(gè)方法表示IOC容器的正式啟動(dòng)阐肤。具體來說這個(gè)啟動(dòng)主要包含BeanDefinition的Resource定位养涮、載入和注冊(cè)三個(gè)過程治专。
2.IOC啟動(dòng)流程說明
- 第一個(gè)過程是Resource定位過程褥傍。 這個(gè) Resource定位指的是BeanDefinition的資源定位(例如我們平時(shí)Spring項(xiàng)目中配置的各種xml配置統(tǒng)一抽象為Resource資源),它由ResourceLoader通過統(tǒng)一的Resource接口來完成宋雏,這個(gè)Resource對(duì)這種形式的BeanDefinition的使用提供了統(tǒng)一接口芜飘。
- 第二個(gè)過程是BeanDefinition的載入過程。 載入過程是把用戶定義好的Bean表示成IOC容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu)即BeanDefinition磨总。BeanDefinition實(shí)際上就是POJO對(duì)象在IOC容器中的抽象嗦明,通過對(duì)BeanDefinition定義的數(shù)據(jù)結(jié)構(gòu),使IOC容器能夠方便的對(duì)POJO對(duì)象也就是Bean對(duì)象進(jìn)行管理蚪燕。
- 第三個(gè)過程就是BeanDefinition的向IOC的注冊(cè)過程娶牌。 這個(gè)過程主要是通過BeanDefinitionRegistry接口完成實(shí)現(xiàn)的。注冊(cè)過程是把載入過程中解析得到的BeanDefinition向IOC容器進(jìn)行注冊(cè)馆纳。其實(shí)IOC內(nèi)部就是將解析得到的BeanDefinition注入到一個(gè)HashMap中去诗良,IOC容器就是通過這個(gè)HashMap持有這些BeanDefinition數(shù)據(jù)的。
3.源代碼解析
FileSystemXmlApplicationContext為例鲁驶,核心繼承關(guān)系為:
FileSystemXmlApplicationContext核心繼承關(guān)系
示例代碼為:
FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:bean.xml")
當(dāng)我們執(zhí)行上面這行代碼的時(shí)候一個(gè)IOC的資源定位鉴裹、解析、注冊(cè)過程就被完成钥弯,下面我們就分析一下上述代碼的核心執(zhí)行流程径荔。
/**
* Create a new FileSystemXmlApplicationContext, loading the definitions
* from the given XML file and automatically refreshing the context.
* @param configLocation file path
* @throws BeansException if context creation failed
*/
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
我們選用的構(gòu)造器為傳入一個(gè)資源文件路徑,實(shí)際調(diào)用的內(nèi)部構(gòu)造器為:
/**
* Create a new FileSystemXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of file paths
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public FileSystemXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
// 父容器設(shè)置
super(parent);
// 設(shè)置資源訪問路徑
setConfigLocations(configLocations);
// 刷新啟動(dòng)容器
if (refresh) {
refresh();
}
}
當(dāng)我們執(zhí)行refresh()
方法的時(shí)候脆霎,我們的ApplicationContext高級(jí)上下文容器就已經(jīng)創(chuàng)建好了总处,我們進(jìn)入refresh()
方法區(qū)查看具體執(zhí)行的邏輯:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 刷新啟動(dòng)前的準(zhǔn)備工作
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 獲取Beanfatory->資源的定位和解析就是在此方法中執(zhí)行的
//(1)AbstractApplicationContext#obtainFreshBeanFactory()
//(2)AbstractApplicationContext#refreshBeanFactory()實(shí)際執(zhí)行子類
//(3)AbstractRefreshableApplicationContext#refreshBeanFactory()的方法
創(chuàng)建DefaultListableBeanFactory并loadBeanDefinitions`
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 配置BeanFactory標(biāo)準(zhǔn)Context特征,比如 classloader睛蛛,后置處理等鹦马。
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 允許添加BeanFactoryProcessor來修改beanFactory,子類覆蓋方法做額外處理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 回調(diào) 上面收集到的所有的 BeanFactoryProcessor 了
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注冊(cè)bean的處理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 國際化相關(guān)的初始化
initMessageSource();
// Initialize event multicaster for this context.
// 初始化應(yīng)用事件的廣播
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 留給子類Context實(shí)現(xiàn)一些特殊處理的模板方法(模板方法留給子類實(shí)現(xiàn))
onRefresh();
// Check for listener beans and register them.
// 注冊(cè)監(jiān)聽器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 單例實(shí)例化
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 完成刷新-推送相應(yīng)的事件
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...
// 清理那些不需要的緩存數(shù)據(jù)
resetCommonCaches();
}
}
}