博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring IOC篇二:xml的核心逻辑处理(doLoadBeanDefinitions(inputSource, encodedResource.getResource()))...
阅读量:4335 次
发布时间:2019-06-07

本文共 9808 字,大约阅读时间需要 32 分钟。

2.1 doLoadBeanDefinitions(inputSource, encodedResource.getResource())

/**     * Actually load bean definitions from the specified XML file.     * @param inputSource the SAX InputSource to read from     * @param resource the resource descriptor for the XML file     * @return the number of bean definitions found     * @throws BeanDefinitionStoreException in case of loading or parsing errors     * @see #doLoadDocument     * @see #registerBeanDefinitions     */    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)            throws BeanDefinitionStoreException {        try {             //获取XML的验证方式,加载XML文件得到对应的Document            Document doc = doLoadDocument(inputSource, resource);            //根据返回的Dcoument注册Bean信息            return registerBeanDefinitions(doc, resource);        }        .........................................   }

2,2 Document doc = doLoadDocument(inputSource, resource);

/**     * Actually load the specified document using the configured DocumentLoader.     * @param inputSource the SAX InputSource to read from     * @param resource the resource descriptor for the XML file     * @return the DOM Document     * @throws Exception when thrown from the DocumentLoader     * @see #setDocumentLoader     * @see DocumentLoader#loadDocument     */    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {        return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,                getValidationModeForResource(resource), isNamespaceAware());    }

2.2.3  getValidationModeForResource(resource) DTD或者XSD文件格式的读取

 

/**     * Gets the validation mode for the specified {
@link Resource}. If no explicit * validation mode has been configured then the validation mode is * {
@link #detectValidationMode detected}. *

Override this method if you would like full control over the validation * mode, even when something other than {

@link #VALIDATION_AUTO} was set. */ 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; }

 

自动检测的代码逻辑分析:

先定义一个变量 isDtdValidated 是否是DTD约束 默认是 false,然后一行行的读取xml资源文件,如果里面包含 DOCTYPE  字符串则是DTD约束,则上返回,停止自动检测。

 

int detectedMode = detectValidationMode(resource);public int detectValidationMode(InputStream inputStream) throws IOException {        // Peek into the file to look for DOCTYPE.        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));        try {                        boolean isDtdValidated = false;            String content;            while ((content = reader.readLine()) != null) {                content = consumeCommentTokens(content);                // 如果读取的行是空行或者注释,则省略                if (this.inComment || !StringUtils.hasText(content)) {                    continue;                }                // 判断是否含有 DOCTYPE 标签                if (hasDoctype(content)) {                    isDtdValidated = true;                    break;                }                if (hasOpeningTag(content)) {                    // End of meaningful data...                    break;                }            }            return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);        }

 

2,2,4 getEntityResolver() 获取资源文件约束的声明

 

entityResolver接口有以下一个方法

 

public abstract InputSource resolveEntity (String publicId,                                               String systemId)        throws SAXException, IOException;}

 

他接受两个参数:publicIdsystemId,并返回InputSource 对象

 

如果是XSD资源文件:
将会读取到以下两个参数:publicId:nullsystemId:http://www.springframework.org/schema/beans/spring-beans-2.5.xsd如果是 DTD约束:
...............................
将会读取到以下两个参数:publicId:-//mybatis.org//DTDsystemId:http://mybatis.org/dtd/mybatis-3-mapper.dtd通过getEntityResolver方法获取EntityResolver接口对象,DelegatingEntityResolver为EntityResolver的实现类。protected EntityResolver getEntityResolver() { if (this.entityResolver == null) { // Determine default EntityResolver to use. ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader != null) { 如果资源加载器不为空,则使用ResourceEntityResolver对象进行文件约束的声明 this.entityResolver = new ResourceEntityResolver(resourceLoader); } else { this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader()); } } return this.entityResolver; }

 

2.2.5 new ResourceEntityResolver(resourceLoader)

public DelegatingEntityResolver(ClassLoader classLoader) {        // 判断是否是DTD约束           this.dtdResolver = new BeansDtdResolver();       //  如果是XSD约束 在获取声明的默认路经是:      // META-INF/spring.schemas        this.schemaResolver = new PluggableSchemaResolver(classLoader);    }

 

2.3 解析并注册 BeanDefinitions

 

 将文件装换为Document以后,接下来的提取以及注册Bean就是我们的重头戏。

 

/**     * Register the bean definitions contained in the given DOM document.     * Called by {
@code loadBeanDefinitions}. *

Creates a new instance of the parser class and invokes * {

@code registerBeanDefinitions} on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */ public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 使用DefaultBeanDefinitionDocumentReader 实例化BeanDefinitionDocumentReader 对象 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();// 记录统计前BeanDefinition的加载个数 int countBefore = getRegistry().getBeanDefinitionCount();// 加载以及注册Bean

 //  这里使用到了单一职责原则,将逻辑处理委托给单一的类进行处理,这个逻辑处理类就是 BeanDefinitionDocumentReader 对象

documentReader.registerBeanDefinitions(doc, createReaderContext(resource));// 统计本次加载Beanfinition的个数        return getRegistry().getBeanDefinitionCount() - countBefore;    }

 

继续深入registerBeanDefinitions方法:

 

/**     * This implementation parses bean definitions according to the "spring-beans" XSD     * (or DTD, historically).     * 

Opens a DOM Document; then initializes the default settings * specified at the {

@code
} level; then parses the contained bean definitions. */ @Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); }

 

继续深入doRegisterBeanDefinitions方法:doRegisterBeanDefinitions算开始真正解析XML文件了。

 

protected void doRegisterBeanDefinitions(Element root) {        // Any nested 
elements will cause recursion in this method. In // order to propagate and preserve
default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); // 处理profile 属性 if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { return; } } } // 空代码留给子类去实现 模板设计模式 继承 DefaultBeanDefinitionDocumentReader 的子类咋XML解析前做一些处理,可以实现此方法 preProcessXml(root); // 解析除了 profile以外的属性 parseBeanDefinitions(root, this.delegate); // 空代码留给子类去实现 模板设计模式 继承 DefaultBeanDefinitionDocumentReader 的子类咋XML解析后做一些处理,可以实现此方法 postProcessXml(root); this.delegate = parent; }

 

2.4 判断标签的解析方式

 

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {      // 对Bean的处理        if (delegate.isDefaultNamespace(root)) {            NodeList nl = root.getChildNodes();            for (int i = 0; i < nl.getLength(); i++) {                Node node = nl.item(i);                if (node instanceof Element) {                    Element ele = (Element) node;                    if (delegate.isDefaultNamespace(ele)) {                  // 默认标签解析    parseDefaultElement(ele, delegate);                    }                    else {                  // 自定义标签解析                        delegate.parseCustomElement(ele);                    }                }            }        }        else {          // 自定义标签解析            delegate.parseCustomElement(root);        }    }

 

转载于:https://www.cnblogs.com/histlyb/p/8976635.html

你可能感兴趣的文章
如何找出错误ora-07445发生时系统执行的语句
查看>>
debain mariadb10配置root
查看>>
Struts2.3+Spring4.0
查看>>
C# 串口编程 — MVVM MVVM Light 实例
查看>>
android之View坐标系(view获取自身坐标的方法和点击事件中坐标的获取)
查看>>
Swift之高德地图自定义标注弹出气泡样式
查看>>
iOS-生成国际化包-配置App多语言支持
查看>>
Android bitmap图片处理
查看>>
Android Studio ndk-Jni开发详细
查看>>
Technical Artist的不归路 —— Kajiya-Kay Shading
查看>>
[Machine Learning]kNN代码实现(Kd tree)
查看>>
利用vue和jQuery实现中国主要城市搜索与选择
查看>>
java代码打包成jar以及转换为exe
查看>>
acm算法模板(1)
查看>>
Python之路【第十四篇】:AngularJS --暂无内容-待更新
查看>>
NOIP模拟题——来自风平浪静的明天
查看>>
Linux 系统的目录结构_【all】
查看>>
李嘉诚语录_1
查看>>
5、javascript倒计时跳转
查看>>
CentOS-6.4无线上网命令行配置
查看>>