config.xml理会为org.w3c.dom.Document
本文首先来简朴看一下MyBatis中将config.xml理会为org.w3c.dom.Document的流程,代码为上文的这部门:
static { try { reader = Resources.getResourceAsReader("mybatis/config.xml"); ssf = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } }
第3行的代码实现为:
public static Reader getResourceAsReader(String resource) throws IOException { Reader reader; if (charset == null) { reader = new InputStreamReader(getResourceAsStream(resource)); } else { reader = new InputStreamReader(getResourceAsStream(resource), charset); } return reader; }
相当于就是将输入的路径转换为一个字符输入流并返回。
接着继承看静态块第4行的代码,new SqlSessionFactoryBuilder().build(reader),把代码定位到SqlSessionFactoryBuilder类的builder要领,这里利用了多态,直接跟到build要领:
public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } }
理会config.xml的代码在第3行XMLConfigBuilder类的结构要领中,看一下XMLConfigBuilder类的结构要领做了什么:
public XMLConfigBuilder(Reader reader, String environment, Properties props) { this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props); }
这里的要害是第二行代码的第一个参数XPathParser,看一下实例化XPathParser类的代码:
public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) { commonConstructor(validation, variables, entityResolver); this.document = createDocument(new InputSource(reader)); }
第2行的代码commonConstructor要领没什么悦目标,将validation、variables、entityResolver配置到XPathParser类的参数中罢了,顺便再实例化一个javax.xml.xpath.XPath出来,XPath用于在XML文档中通过元素和属性举办导航,并对元素和属性举办遍历。
接着看第3行的createDocument要领:
private Document createDocument(InputSource inputSource) { // important: this must only be called AFTER common constructor try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 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 { } }); return builder.parse(inputSource); } catch (Exception e) { throw new BuilderException("Error creating document instance. Cause: " + e, e); } }
看一下第5行~第11行的代码配置DocumentBuilderFactory中参数的寄义:
第13行的代码由配置的参数从DocumentBuilderFactory中获取一个DocumentBuilder实例DocumentBuilderImpl,并由第14行的代码配置一个实体理会器,由第15行~第29行的代码配置一个错误处理惩罚器。
最后看一下第30行的代码parse要领:
public Document parse(InputSource is) throws SAXException, IOException { if (is == null) { throw new IllegalArgumentException( DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "jaxp-null-input-source", null)); } if (fSchemaValidator != null) { if (fSchemaValidationManager != null) { fSchemaValidationManager.reset(); fUnparsedEntityHandler.reset(); } resetSchemaValidator(); } domParser.parse(is); Document doc = domParser.getDocument(); domParser.dropDocumentReferences(); return doc; }