1. 简介 1.1 系列内容
本系列文章讲解的是mybatis解析配置文件内部的逻辑, 即
Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);其背后的逻辑。
1.2 适合对象了解如何使用 mybatis 来访问数据库。可参看《mybatis 初步使用(IDEA的Maven项目, 超详细)》;
具备 DOM 解析 XML 的基本知识。 可参考《mybatis源码-解析配置文件(一)之XML的DOM解析方式。
了解整个配置文件解析是什么样的一个流程。可参考《mybatis源码-解析配置文件(二)之解析的流程》。
1.3 本文内容Configuration类的讲解;
parser.parse()将配置解析到Configuration中的过程;
2. 配置文件mybatis使用到了配置文件, 本文中, 不讲解 mapper.xml, 后续会另开章节重点讲解。
2.1 mysql.properties这是存储数据库信息的对应文件。
mysql.driver=com.mysql.jdbc.Driver mysql.url=jdbc:mysql://localhost:3306/mybatis mysql.username=root mysql.password=jim666 2.2 mybatis-config.xml核心配置文件, 管理 mybatis 的运行行为。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置全局属性 --> <properties resource="mysql.properties"> </properties> <settings> <setting value="LOG4J"/> </settings> <typeAliases> <package/> </typeAliases> <environments default="development"> <environment> <transactionManager type="JDBC"> <property value=""/> </transactionManager> <dataSource type="POOLED"> <property value="${mysql.driver}"/> <property value="${mysql.url}"/> <property value="${mysql.username}"/> <property value="${mysql.password}"/> </dataSource> </environment> </environments> <mappers> <package/> </mappers> </configuration> 3. Configuration 类及其解析Configuration类对应的就是我们的 mybatis-config.xml 配置文件, 我们配置的信息经过解析后就会存储到Configuration的成员变量中。
3.1 解析入口解析的入口是以下的函数:
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }首先通过parser.evalNode("/configuration")函数解析解析出 configuration节点, 在使用parseConfiguration函数解析获得旗下各个节点的信息。
private void parseConfiguration(XNode root) { try { //issue #117 read properties first <!--解析 properties 节点--> propertiesElement(root.evalNode("properties")); <!--解析 settings 节点--> Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); <!--解析 typeAliases 节点--> typeAliasesElement(root.evalNode("typeAliases")); <!--解析 plugins 节点--> pluginElement(root.evalNode("plugins")); <!--解析 objectFactory 节点--> objectFactoryElement(root.evalNode("objectFactory")); <!--解析 objectWrapperFactory 节点--> objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); <!--解析 reflectorFactory 节点--> reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 <!--解析 environments 节点, 需要在 objectFactory 和 objectWrapperFactory才能读取--> environmentsElement(root.evalNode("environments")); <!--解析 databaseIdProvider 节点--> databaseIdProviderElement(root.evalNode("databaseIdProvider")); <!--解析 typeHandlers 节点--> typeHandlerElement(root.evalNode("typeHandlers")); <!--解析 mappers 节点--> mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } } 3.2 常用函数 3.2.1 获取节点其实就是使用 DOM 结合 Xpath 的方法获得各个节点。
public XNode evalNode(String expression) { return evalNode(document, expression); }而后返回相应的 XNode 类对象。
public XNode evalNode(Object root, String expression) { Node node = (Node) evaluate(expression, root, XPathConstants.NODE); if (node == null) { return null; } return new XNode(this, node, variables); }最终调用的是xpath.evaluate(expression, root, returnType), 不理解这个过程的可参考之前的文章。
private Object evaluate(String expression, Object root, QName returnType) { try { return xpath.evaluate(expression, root, returnType); } catch (Exception e) { throw new BuilderException("Error evaluating XPath. Cause: " + e, e); } } 3.2.2 获取子节点 public List<XNode> getChildren() { List<XNode> children = new ArrayList<XNode>(); NodeList nodeList = node.getChildNodes(); if (nodeList != null) { for (int i = 0, n = nodeList.getLength(); i < n; i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { children.add(new XNode(xpathParser, node, variables)); } } } return children; }