XMLConfigBuilder的创建过程
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
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 XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
在创建XMLConfigBuilder中,发现先创建了XPathParser类,这个类是什么呢?
// 代表要解析的整个XML文档
private final Document document;
// 是否开启验证
private boolean validation;
// EntityResolver,通过它可以声明寻找DTD文件的方法,例如通过本地寻找,而不是只能通过网络下载dtd文件
private EntityResolver entityResolver;
// MyBatis配置文件中的properties信息
private Properties variables;
// javax.xml.xpath.XPath工具
private XPath xpath;
这个类主要是mybatis对XML文件进行解析的一个类,Document是mybatis配置文件转化而成的,xpath是java自带的xml解析器,相比Document而言,xpath更方便快捷,语法更简单,是一个轻量级的xml解析器。EntityResolver类主要是进行加载DTD文件的类,如果网络中不顺畅,则采用本地DTD加载。
因为其参数包括Xpath类,因此它是一个增强的Xpath类,里面封装了一些适用于mybatis的解析xml方法。
public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
commonConstructor(validation, variables, entityResolver);
this.document = createDocument(new InputSource(inputStream));
}
创建XPathParser中使用两个方法,分别是commonConstructor和createDocument。
commonConstructor方法是为XPatherParse设置了一些默认值
private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
this.validation = validation;
this.entityResolver = entityResolver;
this.variables = variables;
XPathFactory factory = XPathFactory.newInstance();
this.xpath = factory.newXPath();
}
这段代码最重要的是将xpath创建出来,XPaherParse的解析xml主要靠xpath。
createDocument方法:创建Document对象
private Document createDocument(InputSource inputSource) {
// important: this must only be called AFTER common constructor
try {
// DOM文档创建器的工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(validation);
factory.setNamespaceAware(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(false);
factory.setCoalescing(false);
factory.setExpandEntityReferences(true);
// DOM文档创建器
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);
}
}
好的,现在XPathParse现在创建出来,回到
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
我们先看看XMLConfigBuilder的参数
// 存储是否已经对config文件完成解析
private boolean parsed;
// 解析器
private final XPathParser parser;
// 要读取哪一个Environment节点,这里存储节点名
private String environment;
// 反射工厂
private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
其中,最初要的代码是构造方法的第一行super(new Configuration());这段代码将mybatis中许多注册中心都填充好默认值了,我们下面几章节再将。