上一篇mybatis之SqlSessionFactoryjava
http://my.oschina.net/u/657390/blog/653637node
上一篇對mybatis中SqlSessionFactory的建立過程進行了分析,從以前的分析能夠看出建立過程當中比較重要的一部分是Configuration,這一篇將重點分析配置文件的讀取.sql
以官方的例子來進行分析.express
mybatis-config.xml是mybatis最開始的地方,dataSource,mappers等的配置都在這裏.apache
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
進入SqlSessionFactoryBuilder,能夠看出最終全部的build方法都是調用的如下方法:mybatis
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. } } }
environment:環境,MyBatis 能夠配置成適應多種環境,例如開發,測試和生產.app
XMLConfigBuilder與Configuration之間的關係dom
從這張圖能夠看出使用了建造者模式.ide
在build方法裏涉及到與讀取配置相關的代碼工具
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); //構造方法 //XMLMapperEntityResolver離線MyBatis dtd實體解析器 public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) { this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props); }
比較重要的部分是建立XPathParser實例
new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()) //建立XPathParser實例 public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) { commonConstructor(validation, variables, entityResolver); this.document = createDocument(new InputSource(inputStream)); }
commonConstructor完成的工做以下
private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) { this.validation = validation; this.entityResolver = entityResolver; this.variables = variables; //使用默認的對象模型獲得一個新的XPathFactory實例 XPathFactory factory = XPathFactory.newInstance(); this.xpath = factory.newXPath(); }
XPathFactory,XPath,XPathFactoryImpl,XPath之間的關係
能夠看出使用了工廠方法模式.
接着就是調用createDocument建立document的過程
XMLConfigBuilder建立後調用parse()
parser.parse() //parse()源碼 public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }
主要調用了parseConfiguration其中parser.evalNode("/configuration")獲取到的是根結點
/** * 讀取配置文件組裝configuration * @param root 配置文件的configuration節點 */ private void parseConfiguration(XNode root) { try { //issue #117 read properties first propertiesElement(root.evalNode("properties")); Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
從上面的代碼能夠比較清晰的看出在讀取配置文件的過程比較重要的類有:XNode,XPathParser
XNode是Node類的擴展,XPathParser是xml文件的解析器工具類.
XPathParser中比較重要的方法是:public XNode evalNode(String expression)
evalNode最終調用的是com.sun.org.apache.xpath.internal.jaxp.XPathImpl裏的
public Object evaluate(String expression, Object item, QName returnType)
XPath的相關資料:
http://www.w3school.com.cn/xpath/index.asp
例子
import org.apache.ibatis.io.Resources; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.*; import java.io.IOException; import java.io.InputStream; public class XPathExample { public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException { DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); String resource = "com/analyze/mybatis/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); Document doc = builder.parse(inputStream); XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile("/configuration/mappers/mapper"); Object result = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { System.out.println(nodes.item(i).getAttributes().getNamedItem("resource").getNodeValue()); } } }
xml
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>