作者:zuoxiaolong8810(左潇龙),转载请注明出处。
最近由于工作和生活,学习耽搁了几天,今天我们继续接着上一章,分析FileSystemXmlApplicationContext的构造函数,到底都做了什么,导致IOC容器初始化成功。
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
我们跟踪上一章FileSystemXmlApplicationContext的构造函数,可以发现它最终调用的是上面这个形式重载的构造函数,其中的refresh方法,便是IOC容器初始化的入口。下面我们继续跟踪代码进去看一下refresh方法。refresh方法位于AbstractApplicationContext中,这是一个抽象类,初步实现了ApplicationContext的一般功能,并且这里使用了模板模式,给以后要实现的子类提供了统一的模板。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
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) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
这里面列出了IOC容器初始化的大致步骤,第一步很容易看出来是初始化准备,这个方法里只是设置了一个活动标识,我们主要来看第二步,obtainFreshBeanFactory这个方法,它是用来告诉子类刷新内部的bean工厂,接下来我们跟踪进去看看。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
该方法中第一句便调用了另外一个refreshBeanFactory方法,这个方法是AbstractApplicationContext中的抽象方法,具体的实现并没有在这个抽象类中实现,而是留给了子类,我们追踪到这个子类当中去看一下。该方法又子类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);
}
}
方法加上了final关键字,也就是说此方法不可被重写,可以很清楚的看到,IOC容器的初始化就是在这个方法里发生的,第一步先是判断有无现有的工厂,有的话便会将其摧毁,否则,就会创建一个默认的bean工厂,也就是前面提到的DefaultListableBeanFactory,注意看loadBeanDefinitions(beanFactory);这里,当我们创建了一个默认的bean工厂以后,便是载入bean的定义。这与我们上一章所使用的原始的创建bean工厂的方式极为相似。
看到这里,其实不难看出,FileSystemXmlApplicationContext的初始化方法中,其实已经包含了我们上一章当中原始的创建过程,这个类是一个现有的,spring已经为我们实现好的BeanFactory的实现类。在项目当中,我们经常会用到。
今天天色已晚,改天鄙人带着各位去看一下IOC容器建立的要义,也就是载入bean定义的实现。