MyBatis 源码分析——配置信息
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文件。 |
知道了上面的信息之后,在去看对应的源码你就会发现很简单——大部分都是一一对应的。 来,让我们从上一章中讲到的切入口类(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 源码分析——配置信息的更多相关文章
- MyBatis源码分析-MyBatis初始化流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析(5)——内置DataSource实现
@(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...
- MyBatis源码分析(2)—— Plugin原理
@(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...
- 【MyBatis源码分析】select源码分析及小结
示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...
- MyBatis源码分析之环境准备篇
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
- Mybatis源码分析-StatementHandler
承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...
- mybatis源码分析(一)
mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...
- 【MyBatis源码分析】环境准备
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
随机推荐
- 20155223 Exp7 网络欺诈防范
20155223 Exp7 网络欺诈防范 基础问题回答 通常在什么场景下容易受到DNS spoof攻击? 无设防或防护力特别弟弟低的公共局域网,或者是在同一个局域网下. 在日常生活工作中如何防范以上两 ...
- WPF编程,通过Double Animation动态旋转控件的一种方法。
原文:WPF编程,通过Double Animation动态旋转控件的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/art ...
- [GitHub]GitHub for Windows离线安装的方法
这几天一直在尝试安装GitHub for windows ,安装程序是从https://windows.github.com/ 下载到的OneClick 部署程序,版本号为2.11.0.5.可能是因为 ...
- Linux rhel7 无线网络配置
前言: 手提新装rhel7, ifconfig 发现只有lo 怎么办? 1. 检查网卡驱动装了没有: nmcli -a|grep wlp\ 如果没安装: a. lspci|grep Wireless ...
- 巧用ios朗读kindle图书
想必大家都有想过kindle出中文的有声阅读刊物吧? 今天突发奇想想到一招能够让我们听自己拿kindle买的中文图书.当然这是有条件的. 前提是你得有一个ios设备,不管是iphone还是ipad,i ...
- 【中间件】Redis 实战之主从复制、高可用、分布式
目录 简介 持久化 主从复制 高可用 Redis-Sentinel .NET Core开发 分布式 Redis-Cluster 配置说明 常见问题 简介 本节内容基于 CentOS 7.4.1708, ...
- Unity3D — — UGUI之简易背包
Uinity版本:2017.3 最近在学Siki老师的<黑暗之光RPG>教程,由于教程内用的是NGUI实现,而笔者本人用的是UGUI,所以在这里稍微写一下自己的实现思路(大致上和NGUI一 ...
- 使用jQuery的分页插件jquery.pagination.js进行分页
1,需要用到jquery.pagination.js和pagination.css https://pan.baidu.com/s/1G3PLQSRGjvLxl2ryqpV76w https://pa ...
- Linux内核分析-构造一个简单的Linux系统MenuOS
构造一个简单的Linux系统MenuOS linux内核目录结构 arch目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel C ...
- 第二个Sprint冲刺总结
第二个Sprint冲刺总结 ( 1)团队Github: https://github.com/ouqifeng/EasyGoOperation.git ( 2 ) 团队贡献分: 廖焯燊:22 何武鹏: ...