2.菜鸟总结spring源码——获取Document

1.上一篇文档大概回顾了Resource resource = new ClassPathResource("beanFactoryTest.xml")的加载机制;

   本次回顾从 BeanFactory factory = new XmlBeanFactory(resource);这句话开始;
   public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
   }
   其中reader就是 XmlBeanDefinitionReader类的对象;

   首先从构造方法看起:EncodeResource实际就是对流做了一层封装;


   

我们再次整理一下数据准备阶段的逻辑,首先对传入的resource参数进行封装,目的是考虑可能存在的编码要求的情况,其次是通过SAX读取XML文件的方式来准备InputSource对象,最后把准备的数据传入核心处理部分doLoadBeanDefinitions(inputSource, encodedResource.getResource());

下面进入doLoadBeanDefinitions()方法:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			Document doc = doLoadDocument(inputSource, resource);
			return registerBeanDefinitions(doc, resource);
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (SAXParseException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
		}
		catch (SAXException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"XML document from " + resource + " is invalid", ex);
		}
		catch (ParserConfigurationException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Parser configuration exception parsing XML from " + resource, ex);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"IOException parsing XML document from " + resource, ex);
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Unexpected exception parsing XML document from " + resource, ex);
		}
	}
这个方法除去异常,其实只做了三件事:

(1):获取对XML文件的验证模式  ;(2):加载XML文件,并得到对应的Document;(3)根据Document注册Bean信息;

下面进入doLoadDocument方法:

这个doLoadDocument方法关注两个点:getValidationModeForResource()方法:此方法就是获取资源的验证模式DTD和XSD两个模式,还有一个时genEntityResolver()方法

下面进入这个方法:getValidationModeForResource()

protected int getValidationModeForResource(Resource resource) {
   //如果手动指定了验证模式就用手工指定的验证模式;
   int validationModeToUse = getValidationMode();
   if (validationModeToUse != VALIDATION_AUTO) {
      return validationModeToUse;
   }
   //如果未指定则使用自动检测;
   int detectedMode = detectValidationMode(resource);
   if (detectedMode != VALIDATION_AUTO) {
      return detectedMode;
   }
   // Hmm, we didn't get a clear indication... Let's assume XSD,
   // since apparently no DTD declaration has been found up until
   // detection stopped (before finding the document's root tag).
   return VALIDATION_XSD;
}
下面进入

genEntityResolver():

protected EntityResolver getEntityResolver() {
	if (this.entityResolver == null) {
	// Determine default EntityResolver to use.
	ResourceLoader resourceLoader = getResourceLoader();
	if (resourceLoader != null) {
		this.entityResolver = new ResourceEntityResolver(resourceLoader);
	}else {
		this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
		}
	}
	return this.entityResolver;
	}
那么EntityResolver到底是做什么用的呢;验证文件默认加载方式是通过URL进行网络下载获取的,这样会造成延迟,用户体验也不好,一般的做法都是将验证文件放置在自己的工程里,那么怎么才能将这个URL转化为自己的工程里面呢?以加载DTD文件为例来看看spring中是如何实现的,
@Override
@Nullable
public InputSource resolveEntity(String publicId, @Nullable String systemId) throws IOException {
	if (logger.isTraceEnabled()) {
		logger.trace("Trying to resolve XML entity with public ID [" + publicId +
					"] and system ID [" + systemId + "]");
	}
	if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
		int lastPathSeparator = systemId.lastIndexOf("/");
		int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);
		if (dtdNameStart != -1) {
		//spring-beans + .dtd
		String dtdFile = DTD_NAME + DTD_EXTENSION;
		if (logger.isTraceEnabled()) {
		logger.trace("Trying to locate [" + dtdFile + "] in Spring jar onclasspath");
		}
	try {
	//此构造方法传入getClass()    文件名需要和此类在同一个包中;
	// Resource resource = new ClassPathResource("文件名")   以classpath为基础的
	Resource resource = new ClassPathResource(dtdFile, getClass());
	InputSource source = new InputSource(resource.getInputStream());
	source.setPublicId(publicId);
	source.setSystemId(systemId);
	if (logger.isDebugEnabled()) {
		logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
	}
	return source;
	}
	catch (IOException ex) {
		if (logger.isDebugEnabled()) {
	logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
		}
	}

	}
	}
        // Use the default behavior -> download from website or wherever.
	return null;
}
下面就进入构造document了:步骤为

1.DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

2.DocumentBuilder builder = factory.newDocumentBuilder();

3.builder.parse(inputSource);

下面为详细代码--- 获取factory:


     第二步为:获取DocumentBuilder


   第三步为:用builder构造document


至此已经获取document文档。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值