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;
}