MyBatis原理分析之三:初始化(配置文件读取和解析)

1. 准备工作

编写测试代码(具体请参考《Mybatis入门示例》),设置断点,以Debug模式运行,具体代码如下:

Java代码  

  1. String resource = "mybatis.cfg.xml";
  2. Reader reader = Resources.getResourceAsReader(resource);
  3. SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
  4. SqlSession session = ssf.openSession();

2.源码分析

我们此次就对上面的代码进行跟踪和分析,let‘s go。

首先我们按照顺序先看看第一行和第二行代码,看看它主要完成什么事情:

Java代码  

  1. String resource = "mybatis.cfg.xml";
  2. Reader reader = Resources.getResourceAsReader(resource);

读取Mybaits的主配置配置文件,并返回该文件的输入流,我们知道Mybatis所有的SQL语句都写在XML配置文件里面,所以第一步就需要读取这些XML配置文件,这个不难理解,关键是读取文件后怎么存放。

我们接着看第三行代码(如下),该代码主要是读取配置文件流并将这些配置信息存放到Configuration类中。

Java代码  

  1. SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);

SqlSessionFactoryBuilder的build的方法如下:

Java代码  

  1. public SqlSessionFactory build(Reader reader) {
  2. return build(reader, null, null);
  3. }

其实是调用该类的另一个build方法来执行的,具体代码如下:

Java代码  

  1. public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
  2. try {
  3. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
  4. return build(parser.parse());
  5. } catch (Exception e) {
  6. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  7. } finally {
  8. ErrorContext.instance().reset();
  9. try {
  10. reader.close();
  11. } catch (IOException e) {
  12. // Intentionally ignore. Prefer previous error.
  13. }
  14. }
  15. }

我们重点看一下里面两行:

Java代码  

  1. //创建一个配置文件流的解析对象XMLConfigBuilder,其实这里是将环境和配置文件流赋予解析类
  2. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
  3. // 解析类对配置文件进行解析并将解析的内容存放到Configuration对象中,并返回SqlSessionFactory
  4. return build(parser.parse());

这里的XMLConfigBuilder初始化其实调用的代码如下:

Java代码  

  1. private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
  2. super(new Configuration());
  3. ErrorContext.instance().resource("SQL Mapper Configuration");
  4. this.configuration.setVariables(props);
  5. this.parsed = false;
  6. this.environment = environment;
  7. this.parser = parser;
  8. }

XMLConfigBuilder的parse方法执行代码如下:

Java代码  

  1. public Configuration parse() {
  2. if (parsed) {
  3. throw new BuilderException("Each MapperConfigParser can only be used once.");
  4. }
  5. parsed = true;
  6. parseConfiguration(parser.evalNode("/configuration"));
  7. return configuration;
  8. }

解析的内容主要是在parseConfiguration方法中,它主要完成的工作是读取配置文件的各个节点,然后将这些数据映射到内存配置对象Configuration中,我们看一下parseConfiguration方法内容:

Java代码  

  1. private void parseConfiguration(XNode root) {
  2. try {
  3. typeAliasesElement(root.evalNode("typeAliases"));
  4. pluginElement(root.evalNode("plugins"));
  5. objectFactoryElement(root.evalNode("objectFactory"));
  6. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
  7. propertiesElement(root.evalNode("properties"));
  8. settingsElement(root.evalNode("settings"));
  9. environmentsElement(root.evalNode("environments"));
  10. typeHandlerElement(root.evalNode("typeHandlers"));
  11. mapperElement(root.evalNode("mappers"));
  12. } catch (Exception e) {
  13. throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  14. }
  15. }

最后的build方法其实是传入配置对象进去,创建DefaultSqlSessionFactory实例出来. DefaultSqlSessionFactory是SqlSessionFactory的默认实现.

Java代码  

  1. public SqlSessionFactory build(Configuration config) {
  2. return new DefaultSqlSessionFactory(config);
  3. }

最后我们看一下第四行代码:

Java代码  

  1. SqlSession session = ssf.openSession();

通过调用DefaultSqlSessionFactory的openSession方法返回一个SqlSession实例,我们看一下具体是怎么得到一个SqlSession实例的。首先调用openSessionFromDataSource方法。

Java代码  

  1. public SqlSession openSession() {
  2. return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  3. }

下面我们看一下openSessionFromDataSource方法的逻辑:

Java代码  

  1. private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  2. Connection connection = null;
  3. try {
  4. //获取配置信息里面的环境信息,这些环境信息都是包括使用哪种数据库,连接数据库的信息,事务
  5. final Environment environment = configuration.getEnvironment();
  6. //根据环境信息关于数据库的配置获取数据源
  7. final DataSource dataSource = getDataSourceFromEnvironment(environment);
  8. //根据环境信息关于事务的配置获取事务工厂
  9. TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
  10. connection = dataSource.getConnection();
  11. if (level != null) {
  12. //设置连接的事务隔离级别
  13. connection.setTransactionIsolation(level.getLevel());
  14. }
  15. //对connection进行包装,使连接具备日志功能,这里用的是代理。
  16. connection = wrapConnection(connection);
  17. //从事务工厂获取一个事务实例
  18. Transaction tx = transactionFactory.newTransaction(connection, autoCommit);
  19. //从配置信息中获取一个执行器实例
  20. Executor executor = configuration.newExecutor(tx, execType);
  21. //返回SqlSession的一个默认实例
  22. return new DefaultSqlSession(configuration, executor, autoCommit);
  23. } catch (Exception e) {
  24. closeConnection(connection);
  25. throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
  26. } finally {
  27. ErrorContext.instance().reset();
  28. }
  29. }

传入参数说明:

(1)ExecutorType:执行类型,ExecutorType主要有三种类型:SIMPLE, REUSE, BATCH,默认是SIMPLE,都在枚举类ExecutorType里面。

(2)TransactionIsolationLevel:事务隔离级别,都在枚举类TransactionIsolationLevel中定义。

(3)autoCommit:是否自动提交,主要是事务提交的设置。

DefaultSqlSession是SqlSession的实现类,该类主要提供操作数据库的方法给开发人员使用。

这里总结一下上面的过程,总共由三个步骤:

步骤一:读取Ibatis的主配置文件,并将文件读成文件流形式(InputStream)。

步骤二:从主配置文件流中读取文件的各个节点信息并存放到Configuration对象中。读取mappers节点的引用文件,并将这些文件的各个节点信息存放到Configuration对象。

步骤三:根据Configuration对象的信息获取数据库连接,并设置连接的事务隔离级别等信息,将经过包装数据库连接对象SqlSession接口返回,DefaultSqlSession是SqlSession的实现类,所以这里返回的是DefaultSqlSession,SqlSession接口里面就是对外提供的各种数据库操作。

来源: http://chenjc-it.iteye.com/blog/1409984

null

时间: 2024-12-20 21:19:04

MyBatis原理分析之三:初始化(配置文件读取和解析)的相关文章

[精华] RDMA技术原理分析、主流实现对比和解析

替换高清大图 请点击此处输入图片描述  摘要: 远程直接内存访问(即Remote Direct Memory Access)是一种直接内存访问技术,它将数据直接从一台计算机的内存传输到另一台计算机,无需双方操作系统的介入,本文旨在技术引导,详细内容请通过文末"阅读原文"参阅<RDMA原理分析.对比和技术实现解析>电子书. RDMA技术最早出现在Infiniband网络,用于HPC高性能计算集群的互联.传统的基于Socket套接字(TCP/IP协议栈)的网络通信,需要经过操作

Mybatis 原理分析

对于入门程序的流程分析 使用过程 读配置文件 读取配置文件时绝对路径和相对路径(web工程部署后没有src路径)都有一定问题,实际开发中一般有两种方法 使用类加载器,它只能读取类路径的配置文件 使用SerbletContext对象的getRealPath() 创建SqlSessionFactory工厂,使用了建造者模式(Builder Pattern) 使用工厂生产SqlSession对象,使用了工厂模式(Factory Pattern) 使用SqlSession创建Dao接口的代理对象,使用了

mybatis底层源码分析之--配置文件读取和解析

现在企业级开发中ssm是很常见的技术标配,mybatis比hibernate轻量了很多,而且学习成本相对较低,简单易上手. 那么,问题来了,简单好用的mybatis底层到底是如何实现的呢?都使用了什么原理呢? 为了深入的了解底层原理呢,写了几段简单的代码结合debug,开始学习底层咯,直接先上代码. public class XmlReaderTest { @Test public void mybatisXmlReaderTest() { String resourceXml = "mybat

Mybatis原理分析一 从JDBC到Mybaits

1.引言 本文主要讲解JDBC怎么演变到Mybatis的渐变过程,重点讲解了为什么要将JDBC封装成Mybaits这样一个持久层框架.再而论述Mybatis作为一个数据持久层框架本身有待改进之处. 2.JDBC实现查询分析 我们先看看我们最熟悉也是最基础的通过JDBC查询数据库数据,一般需要以下七个步骤: (1)  加载JDBC驱动 (2)  建立并获取数据库连接 (3)  创建 JDBC Statements 对象 (4)  设置SQL语句的传入参数 (5)  执行SQL语句并获得查询结果 (

apache分析之三、配置文件解析

一.可配置型作为当前世界上部署最为广泛的Web服务器,apache具有很好的扩展性.这种扩展性和内核中的扩展性几乎有相同的作用和意义(核心的实现方法也是相同的,这两个实现应该是有相互借鉴的,只是不确定最早是谁提出的,或者两者都不是,而是从另外更早的unix版本中提出,不确定.),但是它的可配置性更好一些,文件的配置可以通过配置文件来设置.各种mod内容在服务器启动的时候可以根据不同的需求进行裁剪.在网络上搜索的时候,无意间看到Apache可以作为A PAtCHy sErver的缩写,可见apac

第5章4节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 命令行参数解析(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 设置好Monkey的CLASSPATH环境变量以指定"/system/framework /framework/monkey.jar"后,/system/bin/monkey这个shell脚本就会通

MyBatis原理总结(手写实现类)

我们在实际开发中,越简单越好,所以都是采用不写Dao实现类的方式.不管是使用xml还是直接配置. 但是MyBatis是支持写Dao实现类的 注意sqlSession是这里面的一个灵魂,有很多执行api 目录结构: 方法: /** * 用户的持久层接口 */ public interface IUserDao { List<User> findAll(); } 实现类: public class UserDaoImpl implements IUserDao { private SqlSessi

[spring源码学习]二、IOC源码——配置文件读取

一.环境准备 对于学习源码来讲,拿到一大堆的代码,脑袋里肯定是嗡嗡的,所以从代码实例进行跟踪调试未尝不是一种好的办法,此处,我们准备了一个小例子: package com.zjl; public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void sayHello

web压测工具http_load原理分析

原文:web压测工具http_load原理分析 一.前言 http_load是一款测试web服务器性能的开源工具,从下面的网址可以下载到最新版本的http_load: http://www.acme.com/software/http_load/ (页面实在太简陋……) 十分令人欣慰的是,这个软件一直在保持着更新(不像webbench,已经是十年的老古董了.webbench的源码分析请参考:http://www.cnblogs.com/xuning/p/3888699.html ),并且更新频率