Spring在初始化過程中要做的事情很多,下面我們就根據(jù)ClassPathXmlApplicationContext初始化看看我們的應(yīng)用走了哪些步驟,我用debug模式下一步步來展現(xiàn)初始化過程。
首先我們看一下ClassPathXmlApplicationContext類的繼承關(guān)系
ClassPathXmlApplicationContext
AbstractXmlApplicationContext
AbstractRefreshableConfigApplicationContext
AbstractRefreshableApplicationContext
AbstractApplicationContext
DefaultResourceLoader
I ResourceLoad
ApplicationContext context = new ClassPathXmlApplicationContext("conf/applicationContext.xml");
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
初始化應(yīng)用上下文,使用ClassPathXmlApplicationContext類新建實(shí)例,初始化這個類,我們可以看到使用super方法初始化了父類,上面繼承樹中所有的類都初始化了;然后把傳送的配置文件目錄設(shè)置為配置文件;調(diào)用refresh方法,這個方法是AbstractApplicationContext類實(shí)現(xiàn)的方法。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//準(zhǔn)備上下文的刷新,
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//得到新的Bean工廠,應(yīng)用上下文加載bean就是在這里面實(shí)現(xiàn)的
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//準(zhǔn)備bean工廠用在上下文中
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//允許子類上下問處理bean工廠
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//請求工廠處理器作為beans注冊在上下文
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//注冊bean處理器攔截bean創(chuàng)建
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//初始化上下文中消息源
initMessageSource();
// Initialize event multicaster for this context.
//初始化上下文中事件廣播
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//初始化其他具體bean
onRefresh();
// Check for listener beans and register them.
//檢查監(jiān)聽bean并注冊
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//實(shí)例化未初始化單例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//最后一步發(fā)布相應(yīng)事件
finishRefresh();
}
obtainFreshBeanFactory方法把配置文件中的bean加載到容器中。調(diào)用AbstractRefreshableApplicationContext的refreshBeanFactory方法,然后調(diào)用loadBeanDefinitioans(beanFactory)方法,這個方法的實(shí)現(xiàn)類是XmlWebApplicationContext的loadBeanDefinitions方法,方法調(diào)用Reader中的loadBeanDefinitions(configLocations)把配置文件傳入Reader。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//這里定義了Reader來讀取Bean,在loadBeanDifinitions方法中傳入reader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
......
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
XmlBeanDefinitionReader中調(diào)用AbstractBeanDefinition中的loadBeanDefinitions(location)方法。把配置文件讀取成Resource后,調(diào)用XmlBeanDefinitionReader中loadBeanDefinitions(Resource)方法,在方法中調(diào)用doLoadBeanDefinitions(InputSource inputSource, Resource resource)傳入?yún)?shù)是文件流和Resource,方法內(nèi)調(diào)用registerBeanDefinitions(Document doc,Resource resource)方法
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
在DocumentReader調(diào)用注冊bean方法中進(jìn)行注冊,調(diào)用DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions方法,在parseBeanDefinitions方法中調(diào)用parseDefaultElement(ele, delegate);方法,判斷如果獲取到的是個bean的話執(zhí)行,processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)方法最后在DefaultListableBeanFactory類中調(diào)用registerBeanDefinition進(jìn)行注冊,注冊的容器是this.beanDefinitionMap.put(beanName, beanDefinition);,這個是初始化的CurrentHashMap類。
容器的初始化以及Bean的注冊就完成了。