您的位置:首页 > 编程语言 > Java开发

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()

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源码总结