Spring读书笔记(一)

以FileSystemXmlApplicationContext为例说说初始化过程,该类是一个支持Xml定义的BeanDefinition的ApplicationContext,从该类的源码来看,只提供了一个方法,getResourceByPath(String path),其余的都是构造器,还是以自己的习惯看看该类的继承关系,
Resource<---DefalutResourceLoader<--AbstractApplicationContext<---AbstractRefreshableApplicationContext<-----AbstractRefreshableConfigApplicationContext<----AbstractXmlApplicationContext<---FileSysteXmlApplicationContext

首先看一个重要的构造器,其中configLoaction代表着以xml形式的配置文件,用数组的形式是因为可以有多个配置文件的存在

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}


其中里面最重要的一个方法就是refresh(),下面看起具体实现,(为了方便说明,里面的部分方法已经去掉),该方法是在父类AbstractApplicationContext类里面实现的

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			

                        //获得configureableListableBeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			try {
			
			     //为了方便说明里面的方法给删掉了
			}

			catch (BeansException ex) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}

下面看看obtainFreshBeanFactory()的实现,从上面的代码可以看出,该方法返回一个ConfigurableListableBeanFractory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();//模版方法,在子类AbstractRefreshableApplicationContext实现了beanFactory创建
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();//getBeanFactory是模版方法,获得了refreshBeanFacotry()里面创建的beanFacto//ry	
		return beanFactory;
	}


其中refreshBeanFactory()方法的实现如下:在创建Ioc容器之前,如果已经有容器存在,那么就把原来的容器销毁和关闭,然后从新建立容器
@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();//主要是讲beanFactory设置为null
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			
			loadBeanDefinitions(beanFactory);//模版方法,在子类AbstractXmlApplicationContext,beanFactory由此传到了子类中
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;//在此处创建了beanFactory
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}



上面这个方法是在AbstractRefreshableApplicationContext中实现的,该类封装了一个主要的的数据private DefaultListableBeanFactory beanFactory,这是要创建的容器
再来看看loadBeanDefinitions这个方法,是在AbstractRefreshableApplicationContextAbstractXmlApplic的子类AbstractXmlApplicationContext中实现的,注意其中前面 创建的beanfactory被传入到了XmlBeanDefitionReader中

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//最终beanFactory传到了XmlBeanDefitionReader中

		loadBeanDefinitions(beanDefinitionReader);
	
	}


loadBeanDefinitions(beanDefinitionReader);首先得到beanDefiniton信息的Resource定位,然后用参数beanDefitionReader读取。

rotected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();//获取resource定位
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);//具体的载入过程,在这里实现。该方法位于 AbstractBeanDefinitionReader中
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

看看继承关系值,XmlBeanDefinitionReader 继承了AbstractBeanDefitionReader,下面看在AbstractBeanDefinition的具体实现

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		
		int counter = 0;
		for (Resource resource : resources) {
			counter += loadBeanDefinitions(resource);//这是个模版方法,具体的实现在子类XmlBeanDefinitionReader 中
		}
		return counter;
	}

//下面看看XmlBeanDefinitionReader中loadBeanDefitions的实现过程
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));//用EncodeResouce对resource进行包装
	}

//其中把传来的resource传入EncodedResource类中,EncodeResource类封装了private final Resource resource; private final String encoding;
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();//获取Resource的输入流InputStream,因为Resource继承了InputStreamSource
			try {
				InputSource inputSource = new InputSource(inputStream);//获取InputSource方法
				if (encodedResource.getEncoding() != null) {//获取resource的encoding
					inputSource.setEncoding(encodedResource.getEncoding());//把该encoding封装到inputsource里面
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());//加载BeanDefinitions具体的实现的地方
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			int validationMode = getValidationModeForResource(resource)                        
			Document doc = this.documentLoader.loadDocument(//把Xml封装成Document
					inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
			return registerBeanDefinitions(doc, resource);//具体的注册过程
		}
		
	}

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(this.getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

说明:在初始化的过程中,首先要要定位到有效的Bean定义信息,spring中用Resource接口来统一这些信息,而这些都由继承了DefaultResourceLoader的ApplicationContext了来实现。
     在进行单元测试的时候,鉴于容器的创建很复杂所以,初始化容器的操作放在JUnit的setUp方法来完成,这样可以防止每次测试后都进行复杂的初始化操作。      beanFactory最终传入到XmlBeanDefinitionReader中进行相应的操作(待续

你可能感兴趣的:(spring,String,null,读书,resources,Parsing)