spring是大家都會用的ioc框架碟狞,但是要真的了解spring還是需要好好研究一下才行啄枕,為此看了一些spring源碼,所以開始寫spring源碼分析的文章族沃,這個是第一篇频祝,先從ioc容器的啟動開始。
我們都知道,spring的ioc容器的最基本的接口就是BeanFactory,而ApplicationContext是包含了BeanFactory的所有信息脆淹,所以ioc容器在啟動的時候就是從AbstractApplicationContext的refresh方法開始的
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) { // 加鎖常空,避免 #refresh() 和 #close() 方法,自身或者對方并行執(zhí)行盖溺。
// Prepare this context for refreshing.
// 準備刷新的上下文
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 初始化 BeanFactory 漓糙,并進行 XML 文件讀取
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 對 BeanFactory 進行各種功能填充。
// TODO 包括對 @Autowired 和 @Qualifier 注解的屬性注入
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 子類覆蓋該方法烘嘱,做 BeanFactory 的額外的處理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 激活各種 BeanFactory 處理器昆禽,例如 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注冊攔截 Bean 創(chuàng)建的 BeanPostProcessor。這里只是注冊蝇庭,真正的調用在 #getBean(...) 的時醉鳖,即 Bean 創(chuàng)建的時候。
// 注意:
// 1. BeanFactoryPostProcessor 作用于 BeanDefinition
// 2. BeanPostProcessor 作用于 Bean
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
// 初始化 Application Event Multicaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 留給子類哮内,來初始化其他特殊的 Bean 對象們
onRefresh();
// Check for listener beans and register them.
// 注冊監(jiān)聽器們
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化非延遲加載的單例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 完成 refresh 邏輯
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();
}
}
}
具體的啟動流程就不說了盗棵,主要是這里有一個onRefresh方法,我們來看AbstractRefreshableWebApplicationContext這個類,在這個類中覆寫了onRefresh方法
protected void onRefresh() {
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
}
這是什么東西北发?別急纹因,我們來看看themeSource是什么。
public static ThemeSource initThemeSource(ApplicationContext context) {
if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
// Make ThemeSource aware of parent ThemeSource.
if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
if (hts.getParentThemeSource() == null) {
// Only set parent context as parent ThemeSource if no parent ThemeSource
// registered already.
hts.setParentThemeSource((ThemeSource) context.getParent());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using ThemeSource [" + themeSource + "]");
}
return themeSource;
}
else {
// Use default ThemeSource to be able to accept getTheme calls, either
// delegating to parent context's default or to local ResourceBundleThemeSource.
HierarchicalThemeSource themeSource = null;
if (context.getParent() instanceof ThemeSource) {
themeSource = new DelegatingThemeSource();
themeSource.setParentThemeSource((ThemeSource) context.getParent());
}
else {
themeSource = new ResourceBundleThemeSource();
}
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +
"': using default [" + themeSource + "]");
}
return themeSource;
}
}
還是不太明白鲫竞?那我們來看看AbstractRefreshableWebApplicationContext的結構
public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext
implements ConfigurableWebApplicationContext, ThemeSource
原來ThemeSource是一個接口,而AbstractRefreshableWebApplicationContext則實現(xiàn)了這個接口,在onRefresh把自己傳進去了辐怕,好吧逼蒙,這塊就先看到這里从绘。
我們直接到XmlWebApplicationContext這個類里,我們發(fā)現(xiàn)AbstractRefreshableApplicationContext類有一個方法loadBeanDefinitions,而XmlWebApplicationContext覆寫了這個方法,我們來看看XmlWebApplicationContext是怎么實現(xiàn)的
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
這里我們要介紹ioc容器里的一個接口BeanDefinitionReader,而XmlBeanDefinitionReader是BeanDefinitionReader的一個實現(xiàn)類,負責對xml的配置文件進行讀取,并放到ioc容器中。當讀取完配置文件后,通過loadBeanDefinitions方法將bean注冊到ioc容器中僵井。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}
至此陕截,ioc容器就啟動完成。
XmlWebApplicationContext的分析就到這里了批什。