ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

mybatis_3源码阅读日记_容器的加载与初始化

2021-01-05 19:57:25  阅读:140  来源: 互联网

标签:初始化 String -- ibatis apache 源码 mybatis org public


SqlSessionFactory的创建

SqlSessionFactory是通过SqlSessionFactoryBuilder工厂类创建的,而不是直接使用构造器。
SqlSessionFactoryBuilder的主要代码如下:

 //SqlSessionFactoryBuilder是一个建造者模式
 public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }
  
 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }
 
 public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

SqlSessionFactory提供了根据字节流、字符流以及直接使用org.apache.ibatis.session.Configuration配置类(后续我们会详细讲到)三种途径的读取配置信息方式,但究其根本都是首先将XML配置文件构建为Configuration配置类,然后将Configuration设置到SqlSessionFactory默认实现DefaultSqlSessionFactory的configurationz字段并返回。主要解析配置文件的逻辑都委托给XMLConfigBuilder了。
XMLConfigBuilder的主要代码

public class XMLConfigBuilder extends BaseBuilder {
	....
	  /**
	   * Description 构造XMLConfigBuilder
	   * @param reader 流
	   * @param environment 
	   * @param props
	   * @author songhongwei s19744
	  * @time 202/1/5 16:44
	   **/
	  public XMLConfigBuilder(Reader reader, String environment, Properties props) {
	    //XPathParser用于SAX解析xml,解析器硬编码为XMLMapperEntityResolver
	    this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
	  }
	  private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
	    //创建Configuration对象,用来保存配置文件的配置
	    super(new Configuration());
	    ErrorContext.instance().resource("SQL Mapper Configuration");
	    this.configuration.setVariables(props);
	    this.parsed = false;
	    this.environment = environment;
	    this.parser = parser;
	  }
	....
}

标签解析类

public class XPathParser {
 private final Document document;
 private boolean validation;
 //XML标签解析器,可使用不通的解析器,通过构造方法传进来,使用到了策略模式
 private EntityResolver entityResolver;
 private Properties variables;
 private XPath xpath;
    /**
    * Description 构造方法
    *
    * @param reader
    *            Reader
    * @param validation
    *            是否进行DTD 校验
    * @param variables
    *            属性配置
    * @param entityResolver 
    *            XML实体节点解析器
    * @author songhongwei s19744
    * @time 202/1/5 19:54
    **/
 public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) {
   commonConstructor(validation, variables, entityResolver);
   this.document = createDocument(new InputSource(reader));
 }
 
 //创建document
 private Document createDocument(InputSource inputSource) {
   // important: this must only be called AFTER common constructor
   try {
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
     factory.setValidating(validation);

     factory.setNamespaceAware(false);
     factory.setIgnoringComments(true);
     factory.setIgnoringElementContentWhitespace(false);
     factory.setCoalescing(false);
     factory.setExpandEntityReferences(true);

     DocumentBuilder builder = factory.newDocumentBuilder();
     builder.setEntityResolver(entityResolver);
     builder.setErrorHandler(new ErrorHandler() {
       @Override
       public void error(SAXParseException exception) throws SAXException {
         throw exception;
       }

       @Override
       public void fatalError(SAXParseException exception) throws SAXException {
         throw exception;
       }

       @Override
       public void warning(SAXParseException exception) throws SAXException {
         // NOP
       }
     });
     return builder.parse(inputSource);
   } catch (Exception e) {
     throw new BuilderException("Error creating document instance.  Cause: " + e, e);
   }
 }
}

XMLConfigBuilder以及解析Mapper文件的XMLMapperBuilder都继承于BaseBuilder。他们对于XML文件本身技术上的加载和解析都委托给了XPathParser,最终用的是jdk自带的xml解析器而非第三方比如dom4j,底层使用了xpath方式进行节点解析。new XPathParser(reader, true, props, new XMLMapperEntityResolver())的参数含义分别是Reader,是否进行DTD 校验,属性配置,XML实体节点解析器。

entityResolver,跟Spring的XML标签解析器一样,有默认的解析器,也有自定义的,主要使用了策略模式,在这里mybatis硬编码为XMLMapperEntityResolver。
XMLMapperEntityResolver的定义如下:

package org.apache.ibatis.builder.xml;

import org.apache.ibatis.io.Resources;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;

/**
 * Offline entity resolver for the MyBatis DTDs.
 *
 * @author Clinton Begin
 * @author Eduardo Macarron
 */
public class XMLMapperEntityResolver implements EntityResolver {

  private static final String IBATIS_CONFIG_SYSTEM = "ibatis-3-config.dtd";
  private static final String IBATIS_MAPPER_SYSTEM = "ibatis-3-mapper.dtd";
  private static final String MYBATIS_CONFIG_SYSTEM = "mybatis-3-config.dtd";
  private static final String MYBATIS_MAPPER_SYSTEM = "mybatis-3-mapper.dtd";

  private static final String MYBATIS_CONFIG_DTD = "org/apache/ibatis/builder/xml/mybatis-3-config.dtd";
  private static final String MYBATIS_MAPPER_DTD = "org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd";

    /**
     * Converts a public DTD into a local one. 将公共的DTD转换为本地模式
     * @param publicId The public id that is what comes after "PUBLIC"
     * @param systemId The system id that is what comes after the public id.
     * @return The InputSource for the DTD
     * @throws org.xml.sax.SAXException If anything goes wrong
     */
  @Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
    try {
      if (systemId != null) {
        String lowerCaseSystemId = systemId.toLowerCase(Locale.ENGLISH);
        if (lowerCaseSystemId.contains(MYBATIS_CONFIG_SYSTEM) || lowerCaseSystemId.contains(IBATIS_CONFIG_SYSTEM)) {
          return getInputSource(MYBATIS_CONFIG_DTD, publicId, systemId);
        } else if (lowerCaseSystemId.contains(MYBATIS_MAPPER_SYSTEM) || lowerCaseSystemId.contains(IBATIS_MAPPER_SYSTEM)) {
          return getInputSource(MYBATIS_MAPPER_DTD, publicId, systemId);
        }
      }
      return null;
    } catch (Exception e) {
      throw new SAXException(e.toString());
    }
  }

 private InputSource getInputSource(String path, String publicId, String systemId) {
    InputSource source = null;
    if (path != null) {
      try {
        InputStream in = Resources.getResourceAsStream(path);
        source = new InputSource(in);
        source.setPublicId(publicId);
        source.setSystemId(systemId);
      } catch (IOException e) {
        // ignore, null is ok
      }
    }
    return source;
  }

}

mybatis解析的时候,引用了本地的DTD文件,和本类在同一个package下,其中的ibatis-3-config.dtd应该主要是用于兼容用途。在其中getInputSource(MYBATIS_CONFIG_DTD, publicId, systemId)的调用里面有两个参数publicId(公共标识符)和systemId(系统标示符),他们是XML 1.0规范的一部分,在mybatis中,systemId指定的是mybatis-3-config.dtd和ibatis-3-config.dtd
调用栈

build:64, SqlSessionFactoryBuilder (org.apache.ibatis.session)
-->build:77, SqlSessionFactoryBuilder (org.apache.ibatis.session)
	--><init>:89, XMLConfigBuilder (org.apache.ibatis.builder.xml)
		--><init>:127, XPathParser (org.apache.ibatis.parsing)
			-->createDocument:261, XPathParser (org.apache.ibatis.parsing)
				-->parse:339, DocumentBuilderImpl (com.sun.org.apache.xerces.internal.jaxp)
					-->parse:243, DOMParser (com.sun.org.apache.xerces.internal.parsers)
						-->parse:141, XMLParser (com.sun.org.apache.xerces.internal.parsers)
							-->parse:771, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
								-->parse:842, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
									-->scanDocument:505, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
										-->next:602, XMLDocumentScannerImpl (com.sun.org.apache.xerces.internal.impl)
											-->next:959, XMLDocumentScannerImpl$PrologDriver (com.sun.org.apache.xerces.internal.impl)
												-->next:1045, XMLDocumentScannerImpl$DTDDriver (com.sun.org.apache.xerces.internal.impl)
													-->dispatch:1151, XMLDocumentScannerImpl$DTDDriver (com.sun.org.apache.xerces.internal.impl)
														-->resolveEntityAsPerStax:997, XMLEntityManager (com.sun.org.apache.xerces.internal.impl)
															-->resolveEntity:110, EntityResolverWrapper (com.sun.org.apache.xerces.internal.util)
																-->resolveEntity:58, XMLMapperEntityResolver (org.apache.ibatis.builder.xml)

未完待续

标签:初始化,String,--,ibatis,apache,源码,mybatis,org,public
来源: https://blog.csdn.net/u010859650/article/details/112243451

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有