承接上一篇。
下面是 refush()方法的源代码。这个方法是在AbstractApplicationContext类中实现的,该类为AbstractApplicationContext的子类。
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.
beanFactory.destroySingletons();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
首先来看这个prepareRefresh()方法,顾名思义,这个是用来做做刷新容器前的准备工作。
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
}
这个方法,先得到了系统时间,然后通过this.activeMonitor来进行同步,这个一个 Object的实例对象,用来进行同步active标志位。
设置active为true,代表当前applicationContext是活动的,查看active的引用点,可以看到所有对 active的操作都是同步在activeMonitor下的,在调用cancelRefresh()和doClose()两个方法的时候会把它设置为false,其中cancelRefresh()代表中止refresh,doClose()则是当前applicationContext的关闭销毁方法。
然后是obtainFreshBeanFactory()的源码,
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isInfoEnabled()) {
logger.info("Bean factory for application context [" + getId() + "]: " +
ObjectUtils.identityToString(beanFactory));
}
if (logger.isDebugEnabled()) {
logger.debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this);
}
return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException(
"I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
}
}
这两个方法都是在WebApplicationContext所继承的父类(包括父类的父类)中实现,从这个 refreshBeanFactory的方法中,我们能看到beanFactory的刷新过程。当存在BeanFactory则销毁容器中的beans,并且销毁容器。我们通过观察这两个有关刷新的类,AbstractApplicationContext,以及AbstractRefreshApplicationContext,会发现原来有关控创建销毁beanfactory的方法都在这里进行实现。并且都是通过synchronized (this.beanFactoryMonitor)对beanFactory进行同步。上面的destroyBeans的方法主要由 xmlBeanFactory继承的DefaultListAbleBeanFactory类的destroySingleton方法实现。一定很想知道,spring 到底是这样清空bean的吧。
public void destroySingletons() {
if (logger.isInfoEnabled()) {
logger.info("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
synchronized (this.disposableBeans) {
String[] disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
}
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
synchronized (this.singletonObjects) {
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
}
}
上面就是spring销毁容器中的单例的bean的方法。注意,一个spring容器中的bean都是单例的,根据xml配置文件的id唯一,如果配置两个id则为两个不同的实例。好,继续看上面方法,设置了一个用于操作单例对象的同步锁,
singletonObjects
这个对象用于存放beanName和bean实例之间的关系,是一个map。
singletonsCurrentlyInDestruction是一个
标志,指示我们目前在destroysingletons。同理,锁住disposeBeans,再通过她的beanName一个个销毁。接着,我们看到了一个个容器对象的清空,完成后,在改变销毁标志位。这就是一个完整的销毁过程,以此,我们也看到了,spring的主要容器对象。
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
以上,我们看到了spring启动之前的清空容器的过程。下面我们来看看beanFactory的创建过程。
DefaultListableBeanFactory beanFactory = createBeanFactory();
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
protected BeanFactory getInternalParentBeanFactory() {
return (getParent() instanceof ConfigurableApplicationContext) ?
((ConfigurableApplicationContext) getParent()).getBeanFactory() : (BeanFactory) getParent();
}