MyBatis框架的启动前期需要加载相关的XML配置信息。从官网上我们可以了解到他具有十几个节点。其中笔者认为比较重要的节点是settings节点、properties节点、environments节点、 transactionManager节点。至于相关的作用到官网看过一篇都会明白。

MyBatis框架的XML配置到底有几个节点,这个必须去查看一下相关的DTD文件才行。DTA文件就在包名为org.apache.ibatis.builder.xml的下面。由于显示的问题笔者只复制出部分来。

<?xml version="1.0" encoding="UTF-8" ?>

<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>

<!ELEMENT databaseIdProvider (property*)>
<!ATTLIST databaseIdProvider
type CDATA #REQUIRED
>

从上面我们就可以看到根节点就是configuration。同时我们也能找到上面笔者提到的比较重要的几个节点。

1.properties 节点:可以把它理解为变量吧。事实上他可以是一个properties文件。
2.settings 节点:MyBatis框架有一些内部需要设置的配置信息。请查看官网对于settings的介绍。
3.typeAliases 节点:设置相应的别名。这样子可以简少重复的编写。
4.typeHandlers 节点:官网叫为类型处理器,大部用于结果集应射到对象的时候需要。
5.environments 节点:这个节点按道理来讲是大家最清楚的。因为设置数据连接的信息就在这里。
6.mappers 节点:对象模型与数据表映射的信息。
注意:笔者这里只是写出可能常用的。

知道了上面的信息之后,在去看对应的源码你就会发现很简单——大部分都是一一对应的。 来,让我们从上一章中讲到的切入口类(SqlSessionFactoryBuilder)的build方法查看进去。SqlSessionFactoryBuilder类里面重载了很多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.
}
}
}

从上面的代码中我们可以看到这个方法有三个参数:

1.Reader reader:XML配置所在的文件流。

2.String environment:指定要执行的环境ID。

3.Properties properties:加载的变理信息。

XMLConfigBuilder类的作用就是用于加载XML配置文件,也可以理解为读取。他的parse方法充分的体现出他的作用来。

  public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
} private void parseConfiguration(XNode root) {
try {
Properties settings = settingsAsPropertiess(root.evalNode("settings"));
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
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);
}
}

从要上面的俩个方法中我们可以看到很眼熟的代码字眼。相信不难看出就是加载各个节点上的信息。事实上如果我们查看一下parse方法的返回类型我们就可以知道这个步骤最后就是为了生成相应的Configuration类实例。可以这样子讲有关配置信息加载最后一定都在Configuration类实例里面。所以查看Configuration类就变得很有意义。源码笔者就不贴出来占地方。

XMLConfigBuilder类源码里面有俩个地方是笔者比较喜欢的。一个是简单封装了读取XML的操作类——XPathParser类。可能对于JAVA来讲这不算什么。笔者从事过C#开发,所以感觉比较深吧。他只是做了一个简单的封装。可是笔者看起来在读取XML便得更加载顺心了——可读性更强了。

 public String evalString(Object root, String expression) {
String result = (String) evaluate(expression, root, XPathConstants.STRING);
result = PropertyParser.parse(result, variables);
return result;
} public Boolean evalBoolean(String expression) {
return evalBoolean(document, expression);
} public Boolean evalBoolean(Object root, String expression) {
return (Boolean) evaluate(expression, root, XPathConstants.BOOLEAN);
} public Short evalShort(String expression) {
return evalShort(document, expression);
}

上面是XPathParser类读取XML文件值各自需要调用的方法。我们可以清楚的可以知道返回类型和调用的节点。笔者认为简单一小步,可是明理一大步。XMLConfigBuilder类源码里面还有一个笔者认为需要去注意学习的地方——MetaClass类。他的功能跟反射有关系,同时用到ReflectorFactory类和Reflector类。他这样子封装之后用到反射功能便得更加的容易理解和可观。过多的介绍还不如自己亲自去看一下体验一下。

好了,现在让我们回过头在来看看build方法最后返回什么才是最重要的。从源码中我们知道他返回的是一个DefaultSqlSessionFactory类型。

public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}

本章的重点类出来了。当程序执行到上面的方法的时候,说明加载配置信息的工作已经结束了。一个新的工作又要开始了。让我们在看一下笔者的例子代码吧。

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
IProductMapper dao = session.getMapper(IProductMapper.class);

笔者调用的没有参数的openSession方法。从这个方法里我们可以看到他又去调用了一个叫openSessionFromDataSource的方法。这个方法才是结果和开始的连接点。

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}

上面的方法中有几个比较重要的类:Executor类、DefaultSqlSession类。其中特别是Executor类。本章就不明讲。后面会讲到。我们可以看到最后返回类是DefaultSqlSession类。对于数据库的增删改查就依赖这个类。

显然文章到了这里就已经把接下来要去了解工作做了一个明确的方法——了解Executor类的功能。这样子我们就可以进一步的了解框架了。

MyBatis 源码分析——配置信息的更多相关文章

  1. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  2. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  3. MyBatis源码分析(5)——内置DataSource实现

    @(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...

  4. MyBatis源码分析(2)—— Plugin原理

    @(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...

  5. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  6. MyBatis源码分析之环境准备篇

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

  7. Mybatis源码分析-StatementHandler

    承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...

  8. mybatis源码分析(一)

    mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...

  9. 【MyBatis源码分析】环境准备

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

随机推荐

  1. 20155239 《网络对抗》Exp4 恶意代码分析

    20155239 <网络对抗>Exp4 恶意代码分析 使用schtasks指令监控系统运行 先在C盘目录下建立一个netstatlog.bat文件,用来将记录的联网结果格式化输出到nets ...

  2. Bluedroid协议栈BTU线程处理HCI数据流程分析

    在蓝牙enable的过程中会进行多个线程的创建以及将线程与队列进行绑定的工作.该篇文章主要分析一下处理hci数据这个 线程. void BTU_StartUp(void) { ... btu_bta_ ...

  3. ECMAScript6——异步操作之Promise

    Promise对象的参数为一个回调函数,这个回调函数有两个参数,分别是resolve, reject(这俩参数的名字可任取),resolve,reject分别表示异步操作执行成功后的回调函数和异步操作 ...

  4. Elasticsearch Java Rest Client API 整理总结 (一)——Document API

    目录 引言 概述 High REST Client 起步 兼容性 Java Doc 地址 Maven 配置 依赖 初始化 文档 API Index API GET API Exists API Del ...

  5. React半科普文

    React半科普文 什么是React getting started 文件分离 Server端编译 定义一个组件 使用property 组件嵌套 组件更新 Virtual DOM react nati ...

  6. 接口自动化测试框架-AIM

    最近在做公司项目的自动化接口测试,在现有几个小框架的基础上,反复研究和实践,搭建了新的测试框架.利用业余时间,把框架总结了下来. AIM框架介绍 AIM,是Automatic Interface Mo ...

  7. 我的小游戏上线海外AppStore完整流程心得

    1,购买一台Mac或者用VMWare 安装Mac OS流程,笔者使用VMWare. 先安装Mac OS 10.13,教程,成功后不要着急安装vmtools, 首先更新系统至最新版,因为真机测试往往需要 ...

  8. redis在php中常用的语法(转)

    String 类型操作 string是redis最基本的类型,而且string类型是二进制安全的.意思是redis的string可以包含任何数据.比如jpg图片或者序列化的对象 $redis-> ...

  9. 微软职位内部推荐-Senior Dev Lead - SharePoint

    微软近期Open的职位: SharePoint is a multi-billion dollar enterprise business that has grown from an on-prem ...

  10. 四种遍历hashMap的方法及比较

    学习怎样遍历Java hashMap及不同方法的性能. // hashMap的遍历 public void testHashMap() { Map<String, String> map ...