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() 方法,自身或者对方并行执行。
// 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 创建的 BeanPostProcessor。这里只是注册,真正的调用在 #getBean(...) 的时,即 Bean 创建的时候。
// 注意:
// 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.
// 注册监听器们
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则实现了这个接口,在onRefresh把自己传进去了,好吧,这块就先看到这里。
我们直接到XmlWebApplicationContext这个类里,我们发现AbstractRefreshableApplicationContext类有一个方法loadBeanDefinitions,而XmlWebApplicationContext覆写了这个方法,我们来看看XmlWebApplicationContext是怎么实现的
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的一个实现类,负责对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的分析就到这里了。