一、mybatis的插件介绍

关于mybatis的插件,我想大家也都用过,就比如最常用的逆向工程,根据表结构生成model,dao,xml文件,还有分页插件,那这些插件的工作原理是怎么样的呢,就比如分页插件,它为什么能改变我们在xml文件中写的sql语句,本文将带大家一起来了解mybatis的插件机制。(由于本人也是在不断学习,文中难免有错误或不足之处,还望指正,本文基于mybatis3.3.0版本),下面将围绕这几个方面

1、插件入口,即怎么把插件注入到mybatis代码里面

2、插件能拦截哪些类或哪些方法

3、举例简易分表插件原理

二、插件入口

在先了解前,我们来一段自定义mybatis插件的代码

 import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*; import java.sql.Connection;
import java.util.Properties; @Intercepts(
value = {
@Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class} // 不同版本的prepare方法参数不一样,高版本的还有一个Integer参数
)
}
)
public class PluginDemo implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target,this);
} @Override
public void setProperties(Properties properties) { }

要自定义mybatis插件,必须得实现Interceptor接口,这个接口有三个抽象方法

1、intercept,这个方法是mybatis的核心方法,要实现自定义逻辑,基本都是改造这个方法,其中invocation参数可以通过反射要获取原始方法和对应参数信息

2、plugin,它的作用是用来生成一个拦截对方,也就是代理对象,使得被代理的对象一定会经过intercept方法,通常都会使用mybatis提供的工具类Plugin来获取代理对象,如果有自己独特需求,可以自定义

3、setProperties,这个方法就是用来设置插件的一些属性

其中@intercepts注解就是用来标明拦截哪些类,哪些方法。

当我们脱离spring容器来使用mybatis的时候,我们通常是这样写代码的

而在mybatisConfig.xml文件中,我们有配置数据库连接信息,插件,别名,mapper文件映射地址等信息,(温馨提示,这些配置有一定顺序,如果不按照顺序配置,则mybatis解析时会抛出异常,详细配置信息可以参考mbatis的dtd文件配置)既然在配置文件中配置了,那肯定也会被解析掉,如下图,在XmlConfigBuild中进行解析

解析后,插件信息会被存储到configuation中InterceptorChain集合里面,这个configuation在mybatis运行周期是一个单例的,它负责存储所有的配置信息

最终,mybatis的插件信息完整的注入到了configuation里面。

二、mybaits插件能拦截哪些类或哪些方法

在正常开发流程中,我们基本都是通过先获取sqlSession,如果不采用自定义配置,在默认的sqlsession实现就是defaultSqlSession,在该类的一个方法里就隐含了融合插件,

其中会获取到executor,这个类是通过configuation获取的,

最终融合插件的方法就是图中红框的代码。它会为原始的executor类生成代理类。从而你在执行executor类的一些方法时,比如query,update方法,会先生成对应的代理对象,myabtis采用的是jdk的动态代理,代理后,你执行executor类的query,update方法时会自动转接到你自定义的插件intercept方法里面,也可以理解为覆盖原来的方法。

通过这,我们大概也可以猜测的出,mybatis插件要拦截的类,很大原因在configuation类中有生成,也不带大家绕弯子了,来看截图

拦截statementHandler接口的实现类,它通过routingStatementHandler来实现路由,最终定向到prepareStatementHandler类

拦截parameterHandler。这个接口是用来封装参数用的,也就是最终将参数设置到sql里面

拦截ResultSetHandler接口,它主要用于处理sql运行返回的结果

总结,mybatis可以拦截的类分四大类

一、executor,executor类可以说是执行sql的全过程,如组装参数,sql改造,结果处理,比较广泛,但实际用的不多

二、StatementHandler,这个是执行sql的过程,可以获取到待执行的sql,可用来改造sql,如分页,分表,最常拦截的类

三、paremeterHandler,这个用来拦截sql的参数,可以自定义参数组装规则

四、resultHandler,这个用来处理结果

三、简易版分表插件

 import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject; import java.sql.Connection;
import java.util.Properties; @Intercepts(
value = {
@Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class}
)
}
)
public class PluginDemo implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable { /**
* 获取被拦截的目前类,在这里是拦截了statementHandler,所有目前类也就是它
* 通过这个类我们可以拿到待执行的sql语句,通常使用mataObject工具类来获取
* 关于这个工具类,大家可自行了解,个人认为这个工具类很强大
*/
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
/**
* 先解释下为什么写成delegate.boundSql就可以拿到boundSql类
* 从前面也可以得知,statementHandler的默认实现是routingStatementHandler。
* 这个类有一个属性statementHandler,属性名就叫delegate,而这个属性的默认实现又是preparedStatementHandler
* 后面这个类又有属性boundSql,所以,最终形成的写法就是delegate.boundSql。
* 所以这也体现了MetaObject工具类的强大,可以通过实例传参,就可以根据属性名获取对应属性值
*/
BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql"); // 待执行的sql,在这里也就是预编译后的sql,即参数位都是?号
String sql = boundSql.getSql();
/**
* 既然拿到了预编译后的sql,那就可以按照你自己的想法为所欲为,如分页,按年分表等等
* 分表的话,个人推荐druid的sql解析器,我认为还是不错的,大家可以自行了解
* 最后改造完sql,别忘了把它设置回去
* metaObject.setValue("delegate.boundSql.sql",sql);
* invocation.proceed,即原始方法的执行
* 注意点就是,因为mybatis插件采用的是代理模式,所以如果存在多个插件,会形成多个代理
* 你如果要拿到最原始的对象,还得进一步进行分解
* 如:while(metaObject.getValue(""h) != null){
* Object obj = metaObject.getValue("h");
* ....
* }
*/
return invocation.proceed();
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target,this);
} @Override
public void setProperties(Properties properties) { }
}

-----------------------------------------------------------------------------------------------------------------------------分界线-------------------------------------------------------------------------------------

以上就是全部内容

mybatis的插件机制的更多相关文章

  1. mybatis插件机制

    目录 mybatis插件机制 主要 类/接口 和 方法 mybatis插件机制实现 mybatis插件机制 mybatis的插件机制使用动态代理实现,不了解的朋友请先了解代理模式和动态代理:插件本质是 ...

  2. MyBatis 源码分析 - 插件机制

    1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 My ...

  3. 精尽MyBatis源码分析 - 插件机制

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  4. 一、mybatis的插件介绍

    摘自:https://www.cnblogs.com/qm-article/p/11785350.html mybatis的插件机制   一.mybatis的插件介绍 关于mybatis的插件,我想大 ...

  5. mybatis插件机制及分页插件原理

    MyBatis 插件原理与自定义插件: MyBatis 通过提供插件机制,让我们可以根据自己的需要去增强MyBatis 的功能.需要注意的是,如果没有完全理解MyBatis 的运行原理和插件的工作方式 ...

  6. mybatis(六)插件机制及分页插件原理

    转载:https://www.cnblogs.com/wuzhenzhao/p/11120848.html MyBatis 通过提供插件机制,让我们可以根据自己的需要去增强MyBatis 的功能.需要 ...

  7. MyBatis(八):MyBatis插件机制详解

    MyBatis插件插件机制简介 ​ MyBatis插件其实就是为使用者提供的自行拓展拦截器,主要是为了可以更好的满足业务需要. ​ 在MyBatis中提供了四大核心组件对数据库进行处理,分别是Exec ...

  8. mybatis插件机制原理

    mybatis插件机制及分页插件原理 参考链接:mybatis插件机制及分页插件原理 如何编写一个自定义mybatis插件 参考链接:mybatis 自定义插件的使用

  9. 关于struts2的过滤器和mybatis的插件的分析

    网上一搜,发现一篇写的非常棒的博文,就直接复制过来了,供以后复习使用. 前辈博文链接:共三篇: http://jimgreat.iteye.com/blog/1616671: http://jimgr ...

随机推荐

  1. electron教程(二): http服务器, ws服务器, 进程管理

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(二): http服务器, ws服务器, 进程管理 electron教程(三): 使 ...

  2. linux常用开发命令总结

    linux常用命令 文件操作命令 1. cd 目录名/目录名  切换目录 cd .. 切换到上一级目录  (change dictionary) Ctrl+C强制退出命令行,回到上一级 2.ls    ...

  3. Spring Cloud Stream 整合 RabbitMQ

    简介 Spring Cloud Stream是一个构建消息驱动微服务的框架,应用程序通过input(相当于consumer).output(相当于producer)来与Spring Cloud Str ...

  4. Google资深工程师深度讲解Go语言★

    课程目录 第1章 课程介绍 第2章 基础语法 第3章 内建容器 第4章 面向“对象” 第5章 面向接口 第6章 函数式编程 第7章 错误处理和资源管理 第8章 测试与性能调优 第9章 Goroutin ...

  5. 【php中的curl】php中curl的详细解说

    本文我来给大家详细介绍下cURL的简单的使用方法,下文我将会给大家详细介绍cURL的高级应用, cURL可以使用URL的语法模拟浏览器来传输数据, FTP, FTPS, HTTP, HTTPS, GO ...

  6. 手把手教你如何在Windows下allure与jenkins的集成生成让你一见钟情的测试报告 - 03(非常详细,非常实用)

    简介 好了,国庆假期结束,开始搬砖.为什么要把allure和jenkins集成了?原因是集成以后,我们就可以直接查看allure的结果,不需要重复输入命令.重复使用浏览器打开文件来查看allure的结 ...

  7. ShaderHelper2 组件升级,支持自动枚举参数!

    ShaderHelper2 组件新体验视频演示: https://www.bilibili.com/video/av69314195/ ShaderHelper2 组件我们已经介绍过两次了,不了解的伙 ...

  8. Flutter学习笔记(29)--Flutter如何与native进行通信

    如需转载,请注明出处:Flutter学习笔记(29)--Flutter如何与native进行通信 前言:在我们开发Flutter项目的时候,难免会遇到需要调用native api或者是其他的情况,这时 ...

  9. React入门学习

    为了获得更好的阅读体验,请访问原地址:传送门 一.React 简介 React 是什么 React 是一个起源于 Facebook 的内部项目,因为当时 Facebook 对于市场上所有的 JavaS ...

  10. The Troublesome Frog

    In Korea, the naughtiness of the cheonggaeguri, a small frog, is legendary. This is a well-deserved ...