主题
《面渣逆袭》MyBatis 篇 · 第 3/3 章。原版 PDF(下载 / 打印)
19. 说说Mybatis的插件运行原理,如何编写一个插件?
插件的运行原理?
Mybatis 会话的运行需要ParameterHandler、ResultSetHandler、StatementHandler、Executor 这四大对象的配合,插件的原理就是在这四大对象调度的时候,插入一些我我们自己的代码。

Mybatis 使用JDK 的动态代理,为目标对象生成代理对象。它提供了一个工具类Plugin,实现了
InvocationHandler交叉。

使用Plugin生成代理对象,代理对象在调用方法的时候,就会进入invoke 方法,在invoke 方法中,如果存在签名的拦截方法,插件的intercept 方法就会在这里被我们调用,然后就返回结果。如果不存在签名方法,那么将直接反射调用我们要执行的方法。
如何编写一个插件?
我们自己编写MyBatis 插件,只需要实现拦截器交叉Interceptor(org.apache.ibatis.plugin
Interceptor),在实现类中对拦截对象和方法进行处理。
实现Mybatis的Interceptor接又并重写intercept()方法这里我们只是在目标对象执行目标方法的前后进行了打印;
java
public class MyInterceptor implements Interceptor {
Properties props=null;@ Override
java
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("before……");
//如果当前代理的是一个非代理对象,那么就会调用真实拦截对象的方法
// 如果不是它就会调用下个插件代理对象的invoke方法
Object obj=invocation.proceed();
System.out.println("after……");
return obj;
}
}然后再给插件编写注解,确定要拦截的对象,要拦截的方法
@ Intercepts({@ Signature(
type = Executor.class, //确定要拦截的对象method="update", // 确定要拦截的方法
java
args = {MappedStatement.class,Object.class} //拦截方法的参数
)})
public class MyInterceptor implements Interceptor {
Properties props=null;@ Override
java
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("before……");
//如果当前代理的是一个非代理对象,那么就会调用真实拦截对象的方法
// 如果不是它就会调用下个插件代理对象的invoke方法
Object obj=invocation.proceed();
System.out.println("after……");
return obj;
}
}最后,再MyBatis 配置文件里面配置插件
<plugins>
<plugin interceptor="xxx.MyPlugin">
<property name="dbType",value="mysql"/>
</plugin>
</plugins>20. MyBatis是如何进行分页的?分页插件的原理是什么?
MyBatis 是如何分页的?
MyBatis 使用RowBounds 对象进行分页,它是针对ResultSet 结果集执行的内存分页,而非物理分页。
可以在sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的原理是什么?
分页插件的基本原理是使用Mybatis 提供的插件交叉,实现自定义插件,拦截Executor 的query 方法在执行查询的时候,拦截待执行的sql,然后重写sql,根据dialect 方言,添加对应的物理分页语句和物理分页参数。
举例:select*fromstudent,拦截sql 后重写为:selectt.from(selectfromstudent)t
limit0,10
可以看一下一个大概的MyBatis 通用分页拦截器:

没有什么使我停留— — 除了目的,纵然岸旁有玫瑰、有绿荫、有宁静的港湾,我是不系之舟。