2.菜鸟总结spring源码——获取Document
2018-01-29 21:30
363 查看
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()
下面进入
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中是如何实现的,
1.DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
2.DocumentBuilder builder = factory.newDocumentBuilder();
3.builder.parse(inputSource);
下面为详细代码--- 获取factory:
第二步为:获取DocumentBuilder
第三步为:用builder构造document
至此已经获取document文档。
本次回顾从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 onclas 4000 spath"); } 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文档。
相关文章推荐
- 【Spring源码从入门到精通】(七)获取Document
- 菜鸟学习Spring——SpringMVC注解版在服务器端获取Json字符串并解析
- Spring源码阅读总结(Ing)
- 从Github获取spring源码 导入 Myeclipse/Eclipse/IDEA 学习
- Spring源码分析总结——Mybatis的整合
- SpringBoot 获取前端页面参数的集中方式总结
- 解析Spring源码(7)--DefaultBeanDefinitionDocumentReader
- Java之美[从菜鸟到高手演变]之Spring源码学习 - 环境搭建
- 菜鸟学习Spring——SpringMVC注解版在服务器端获取Json字符串并解析
- Spring IOC 容器源码分析 - 获取单例 bean
- Spring Boot获取前端页面参数的几种方式总结
- 解析Spring源码(5)--this.documentLoader.loadDocument
- Spring 源码分析(三) —— AOP(四)获取指定增强
- Spring 源码分析《Bean的获取与创建流程》
- spring的4个获取资源总结
- Spring源码分析总结——HttpInvoker
- 在Eclipse上通过插件获取github上的spring源码
- Spring源码阅读——简单模拟Spring的控制反转IOC和依赖注入(Bean的加载和获取)
- Spring 源码分析(四) ——MVC(八)总结
- spring源码分析之spring-core总结篇