从 [MyBatis 原码解析(version:3.2.7)] 中,我们得知,MyBatis去执行SQL都是通过 DefaultSqlSession 中的工具方法去执行的。

那么问题来了,MyBatis 是怎么构造 DefaultSqlSession 的?

通过查看源码,得知 MyBatis 是通过 DefaultSqlSessionFactory 来构造 DefaultSqlSession 的。

DefaultSqlSessionFactory#openSessionFromDataSource(ExecutorType, TransactionIsolationLevel, boolean)

/**
* @param ExecutorType 执行器的类型。MyBatis中提供了三种执行器:SIMPLE, REUSE, BATCH。默认的是 SIMPLE
* @param TransactionIsolationLevel 事务隔离级别
* @param autoCommit 是否自动提交事务
*/
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); // 通过 Environment 获取事务工厂 TransactionFactory。没有指定Environment,则使用 ManagedTransactionFactory
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 从 TransactionFactory 中获取一个 Transaction
final Executor executor = configuration.newExecutor(tx, execType); // 从 Configuration 中获取一个新的 Executor。(Configuration 对应的是 mybatis-config.xml 中的配置)
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();
}
}

重点看一下 Configuration#newExecutor(Transaction transaction, ExecutorType executorType)

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType; // 默认使用 SimpleExecutor
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction); // 使用 BatchExecutor
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction); // 使用 ReuseExecutor
} else {
executor = new SimpleExecutor(this, transaction); // 默认使用 SimpleExecutor
}
if (cacheEnabled) {
executor = new CachingExecutor(executor); // 使用 CachingExecutor
}
executor = (Executor) interceptorChain.pluginAll(executor); // 执行所有的MyBatis拦截器,并返回 Executor
return executor;
}

至此,我们找到了MyBatis的一个扩展点——拦截器interceptor。

MyBatis Inteceptor是使用JDK的动态代理来实现的,所以它只能对接口进行拦截。

里面两个很重要的注解是:@Intercepts、@Signature
@Intercepts : 标记要拦截的方法签名
@Signature : 方法签名,唯一的标记一个接口的方法

通过查看源码,我们还可以知道,MyBatis所有的代理拦截都是通过 InterceptorChain.pluginAll(Object target) 来实现的。
至此,我们得到下图:

通过上图可知,Mybatis支持对 Executor 、 StatementHandler 、 ResultSetHandler 和 PameterHandler 进行拦截,也就是说会对这4种对象进行代理。

Executor                : 作用是执行SQL语句(所有的sql),并且对事务、缓存等提供统一接口。(在这一层上做拦截的权限会更大)
StatementHandler : 作用是对 statement 进行预处理,并且提供统一的原子的增、删、改、查接口。(如果要在SQL执行前进行拦截的话,拦截这里就可以了)
ResultSetHandler  : 作用是对返回结果ResultSet进行处理。
PameterHandler    : 作用是对参数进行赋值。

附:

对 TypeHandler 进行扩展:http://mp.weixin.qq.com/s/GLb_-dLVAWYb6-_GWGIF8w
解决问题:
  从SqlServer中取数据,遇到很多列都是Numeric(10,2)类型,指的是字段是数字型,长度为10,小数为两位。Mybatis默认的BigDecimalTypeHandler取到后,都默认变成4位小数,不够的补了0。而上层的要求是,拿到的和数字相关的数据都要2位小数。这时,可以自定义一个 TypeHandler 进行统一处理

TypeHandler 的作用:无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器 TypeHandler 将获取的值以合适的方式转换成 Java 类型。

MyBatis 支持的扩展点(version:3.2.7)的更多相关文章

  1. mybatis支持jdk8等localdate类型

    大家知道,在实体Entity里面,可以使用java.sql.Date.java.sql.Timestamp.java.util.Date来映射到数据库的date.timestamp.datetime等 ...

  2. EntityFramework中支持BulkInsert扩展

    EntityFramework中支持BulkInsert扩展 本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 前言 很显然,你应该不至于使用 Ent ...

  3. yum 安装apache php 使php支持memcached扩展

    在公司上新项目的时候,无论生产环境还是测试环境,都会让运维安装php 环境(lamp/lnmp),并让php支持memcached 的扩展.这里搭建php环境其实主要就是搭建apache 和php.m ...

  4. 【03】Chrome提示印象笔记剪藏插件"已停用不支持的扩展程序"怎么办?

    [03] Chrome提示印象笔记剪藏插件"已停用不支持的扩展程序"怎么办? 刚好也遇上了这个问题,百度了一下,以下是解决方法,亲测可行: 1.首先把需要安装的第三方插件,后缀.c ...

  5. .net core 3.0 Signalr - 04 使用Redis做底板来支持横向扩展

    在实际的系统中,可能需要多台机器部署;然而,Signalr的连接信息是跟站点走的,举个例子 推送系统部署了A.B两个服务器,张三访问A服务器,李四访问B服务器,当张三通过A服务器向李四推送的时候,A服 ...

  6. 使Jackson和Mybatis支持JSR310标准

    1.首先要确保Jackson和Mybatis正确地整合进项目了 2.添加额外的依赖 <dependency> <groupId>org.mybatis</groupId& ...

  7. 记一次 IDEA mybatis.generator 自定义扩展插件

    在使用 idea mybatis.generator 生成的代码,遇到 生成的代码很多重复的地方, 虽然代码是生成的,我们也不应该允许重复的代码出现,因为这些代码后期都要来手动维护. 对于生成时间戳注 ...

  8. springboot + mybatis 支持oracle和mysql切换含源码

    1.springboot 启动类加入bean 如下 // DatabaseIdProvider元素主要是为了支持不同的数据库@Beanpublic DatabaseIdProvider getData ...

  9. 全网唯一开源java开发的支持高扩展,高性能的Mqtt集群broker!

    SMQTT是一款开源的MQTT消息代理Broker, SMQTT基于Netty开发,底层采用Reactor3反应堆模型,支持单机部署,支持容器化部署,具备低延迟,高吞吐量,支持百万TCP连接,同时支持 ...

随机推荐

  1. Knockout开发中文API系列2–创建数据模型和监控属性

    Observables,这个词的翻译来自汤姆大叔,对于部分翻译不是很准确的,欢迎大家留言,以得到更好的翻译. Knockout是建立在以下3个核心功能之上的: 1.    属性监控与依赖跟踪 2.   ...

  2. Eclipse调试Java的10个技巧【转】

    clipse调试Java的10个技巧 先提三点 不要使用System.out.println作为调试工具 启用所有组件的详细的日志记录级别 使用一个日志分析器来阅读日志 1.条件断点 想象一下我们平时 ...

  3. oracle快速创建可用用户

    执行语句 create user utaptest identified by utaptest; create tablespace utaptestspace datafile 'd:\data. ...

  4. Nginx+php (十六)

    [教程主题]:Nginx+php [课程录制]: 创E [主要内容] [1] 编译PHP 初始环境: 为了省事把所需要的库文件全都安装上,可以使用rpm包安装,也可以用yum命令安装, yum -y  ...

  5. w3svc无法启动

    w3svc无法启动 运行命令regedit,打开注册表编辑器,进入:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP]: a) Cha ...

  6. 多选下拉框带搜索(aps.net)

    自己写了一个带搜索功能的多选下拉框,为了要获取值,就没有封装插件,实现思路 1.一个文本框 做搜索 2.一个文本框显示选中文本,一个隐藏控件存值 3.一个div里面绑定CheckBoxList控件(这 ...

  7. 解決BufferedReader读取UTF-8文件中文乱码(转)

    读取txt文件乱码 BufferedReader read = new BufferedReader(new FileReader(new File(filename))); 解决办法: InputS ...

  8. 使用javascript实现浏览器全屏

    HTML 5中的full screen,目前可以在除IE和opera外的浏览器中使用 ,有的时候用来做 全屏API,游戏呀,等都很有用.先看常见的API 1 element.requestFullSc ...

  9. loadrunner 中Error和failed transaction 的区别

    Down:没有运行 Pending:挂起 Init:初始化 Ready:准备就绪 Run:正在运行 Rendezvous:正在集结 Passed:运行通过 Failed:运行失败 Error:出现故障 ...

  10. Hive之分区(Partitions)和桶(Buckets)

    转自:http://www.aahyhaa.com/archives/316 hive引入partition和bucket的概念,中文翻译分别为分区和桶(我觉的不是很合适,但是网上基本都是这么翻译,暂 ...