Spring源码学习记录--XmlBeanDefinitionReader

 private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded = new NamedThreadLocal<>("XML bean definition resources currently being loaded");

  昨天看Spring加载配置文件源码时,对于XmlBeanDefinitionReader中resourcesCurrentlyBeingLoaded的作用一直很疑惑,今天终于弄明白。特写下此片文章,用于记录

resourcesCurrentlyBeingLoaded是ThreadLocal的,每个线程获取的都是不同的内存。它的作用是为了防止循环加载同一个配置文件(在beans.xml中import本身)

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}
		
		//获取当前线程中已加载的resource
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		//如果resource已经加载,就抛出异常(只有使用import引入自己的配置文件时才会导致异常)
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				/**
				 * doLoadBeanDefinitions解析配置文件时,遇到import标签会递归调用loadBeanDefinitions方法
				 * 这个时候当前加载配置文件不会清除
				 */
				int num = doLoadBeanDefinitions(inputSource, encodedResource.getResource());
				System.out.println(num);
				return num;
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			//每次加载完就会从resourcesCurrentlyBeingLoaded清除掉当前加载的resource文件,
			//这样之后可以重新加载配置文件
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
				System.out.println(this.resourcesCurrentlyBeingLoaded.get());
			}
		}
	}
 

 

猜你喜欢

转载自h140465.iteye.com/blog/2406253
今日推荐