Spring源码阅读3

  承接上一篇。

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

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/awe5566/article/details/11021633
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞