上篇把资源文件“bean.xml” 存储成spring的resourceLoader数组中后。
然后就是通过spring的资源加载器读入bean定义的文件。bean定义的载入过程就是将bean定义资源文件读入内存并解析传换成spring的bean数据机构。
上两步是定位资源文件,现在是解析的过程:
if (refresh) {
refresh();
}
refresh参数,在调用构造函数时候,默认true。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();
//refresh方法就是从这力入口
**ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();**
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
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;
}
}
}
整个refresh()中“ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();”这句以后代码的都是注册容器的信息源和生命周期事件,载入过程就是从这句代码启动。所以我们着重看下这个代码。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
refreshBeanFactory() 抽象方法,在子类AbstractRefreshableApplicationContext中实现。实现如下:
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);
}
}
首先如果有beanFactory 毁灭掉,然后关闭,保证refresh前beanfactory是独一的。
然后创建, 加载 ,存入 beanFactory参数。
loadBeanDefinitions(beanFactory);这个方法在此类中也是一个抽象方法,具体实现在子类AbstractXmlApplicationContext中。而这个方法就是载入资源文件很重要的方法。下篇继续讲解。
注意:心中常有的结构图再显示一下
这个机构中只有ClassPathXmlApplicationContext是正常类,其他都是抽象类,这样便于分层,相关的方法可以放在一层,容易管理。