Spring源码阅读3

来源:互联网 发布:linux daemon 进程 编辑:程序博客网 时间:2024/05/01 22:34

  承接上一篇。

下面是 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();}








原创粉丝点击