以ClassPathXmlApplicationContext为例
1 初始化ClassPathXmlApplicationContext,设置spring相关的xml配置文件
2 调用父类AbstractApplicationContext来启动容器
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
//设置xml路径
setConfigLocations(configLocations);
if (refresh) {
//调用父类启动容器
refresh();
}
}
3 启动方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 3.1 设置启动时间、状态、设置占位符熟悉资源
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 3.2 让子类重新创建一个bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 3.3 给bean工程设置一些标准组件:如ClassLoader、BeanPostProcessor
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 3.4 允许子类进行对beanFactory进行处理,如注册BeanPostProcessor
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 3.5 初始化所有BeanFactoryPostProcessor类型的bean,并调用postProcessBeanFactory,运行对元数据进行修改
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 3.6 注册所有BeanPosrProccessor类型的bean到beanFactory
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 3.7 设置国际化信息
initMessageSource();
// Initialize event multicaster for this context.
// 3.8 初始化消息组播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 3.9 让子类去一些初始化特殊bean
onRefresh();
// Check for listener beans and register them.
// 3.10 注册ApplicationListener到时间组播器,并发布早期的事件
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 3.11 初始化非延时加载的单例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
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();
}
}
}
3.2 让子类重新创建一个bean工厂
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//让子类去刷新beanFactory
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
ClassPathXmlApplicationContext的父类AbstractRefreshableApplicationContext refreshBeanFactory让子类去准备beanFactory的bean元数据,执行读取xml文件、解析xml、处理、注册元数据信息到BeanDefinition。
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
而实际执行xml读取、解析、注册的是: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);
}