Skip to content

《面渣逆袭》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 通用分页拦截器:

配图

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

本文整理自三分恶《面渣逆袭》系列的公开内容,仅供个人学习使用

本站仅供个人学习使用,请勿外传