关于Mybatis插件,大部分人都知道,也都使用过,但很多时候,我们仅仅是停留在表面上,知道Mybatis插件可以在DAO层进行拦截,如打印执行的SQL语句日志,做一些权限控制,分页等功能;但对其内部实现机制,涉及的软件设计模式,编程思想往往没有深入的理解。
本篇案例将帮助读者对Mybatis插件的使用场景,实现机制,以及其中涉及的编程思想进行一个小结,希望对以后的编程开发工作有所帮助。
注:本案例以mybatis 3.4.7-SNAPSHOT版本为例。
PS:挺久之前写的,花了一些心思,就是里面的源码都是图片,哈哈哈,凑合着看吧。
Mybatis插件典型适用场景 分页功能mybatis的分页默认是基于内存分页的(查出所有,再截取),数据量大的情况下效率较低,不过使用mybatis插件可以改变该行为,只需要拦截StatementHandler类的prepare方法,改变要执行的SQL语句为分页语句即可;
公共字段统一赋值一般业务系统都会有创建者,创建时间,修改者,修改时间四个字段,对于这四个字段的赋值,实际上可以在DAO层统一拦截处理,可以用mybatis插件拦截Executor类的update方法,对相关参数进行统一赋值即可;
性能监控对于SQL语句执行的性能监控,可以通过拦截Executor类的update, query等方法,用日志记录每个方法执行的时间;
其它其实mybatis扩展性还是很强的,基于插件机制,基本上可以控制SQL执行的各个阶段,如执行阶段,参数处理阶段,语法构建阶段,结果集处理阶段,具体可以根据项目业务来实现对应业务逻辑。
Mybatis插件介绍 什么是Mybatis插件与其称为Mybatis插件,不如叫Mybatis拦截器,更加符合其功能定位,实际上它就是一个拦截器,应用代理模式,在方法级别上进行拦截。
支持拦截的方法执行器Executor(update、query、commit、rollback等方法);
参数处理器ParameterHandler(getParameterObject、setParameters方法);
结果集处理器ResultSetHandler(handleResultSets、handleOutputParameters等方法);
SQL语法构建器StatementHandler(prepare、parameterize、batch、update、query等方法);
拦截阶段那么这些类上的方法都是在什么阶段被拦截的呢?为理解这个问题,我们先看段简单的代码(摘自mybatis源码中的单元测试SqlSessionTest类),来了解下典型的mybatis执行流程,如下代码所示:
以上代码主要完成以下功能:
读取mybatis的xml配置文件信息
通过SqlSessionFactoryBuilder创建SqlSessionFactory对象
通过SqlSessionFactory获取SqlSession对象
执行SqlSession对象的selectList方法,查询结果
关闭SqlSession
如下是时序图,在整个时序图中,涉及到mybatis插件部分已标红,基本上就是体现在上文中提到的四个类上,对这些类上的方法进行拦截。
Mybatis插件实现机制 插件配置信息的加载先来看下mybatis是如何加载插件配置的,对应的xml配置信息如下:
对应的解析代码如下,主要做以下工作:
根据解析到的类信息创建Interceptor对象;
调用setProperties方法设置属性变量;
添加到Configuration的interceptorChain拦截器链中;
以上逻辑对应的时序图如下:
代理对象的生成Mybatis插件的实现机制主要是基于动态代理实现的,其中最为关键的就是代理对象的生成,所以有必要来了解下这些代理对象是如何生成的。
Executor代理对象
ParameterHandler代理对象
ResultSetHandler代理对象