【原理】MyBatis插件

26 阅读2分钟

mp.weixin.qq.com/s?__biz=MzU…

插件的运行原理

Mybatis会话的运行需要ParameterHandler、ResultSetHandler、StatementHandler、Executor这四大对象的配合,插件的原理就是在这四大对象调度的时候,插入一些我我们自己的代码。

MyBatis插件原理简图.png Mybatis使用JDK的动态代理,为目标对象生成代理对象。它提供了一个工具类Plugin,实现了InvocationHandler接口。

调用插件的intercept方法.png 使用Plugin生成代理对象,代理对象在调用方法的时候,就会进入invoke方法,在invoke方法中,如果存在签名的拦截方法,插件的intercept方法就会在这里被我们调用,然后就返回结果。如果不存在签名方法,那么将直接反射调用我们要执行的方法。

编写插件

我们自己编写MyBatis 插件,只需要实现拦截器接口 Interceptor (org.apache.ibatis. plugin Interceptor ),在实现类中对拦截对象和方法进行处理。

// 1 实现Mybatis的Interceptor接口并重写intercept()方法
public class MyInterceptor implements Interceptor {
    Properties props=null;
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("before……");
        //如果当前代理的是一个非代理对象,那么就会调用真实拦截对象的方法
        // 如果不是它就会调用下个插件代理对象的invoke方法
        Object obj=invocation.proceed();
        System.out.println("after……");
        return obj;
    }
}
// 2 然后再给插件编写注解,确定要拦截的对象,要拦截的方法
@Intercepts({@Signature(
        type = Executor.class,  //确定要拦截的对象
        method = "update",        //确定要拦截的方法
        args = {MappedStatement.class,Object.class}   //拦截方法的参数
)})
public class MyInterceptor implements Interceptor {
    Properties props=null;
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("before……");
        //如果当前代理的是一个非代理对象,那么就会调用真实拦截对象的方法
        // 如果不是它就会调用下个插件代理对象的invoke方法
        Object obj=invocation.proceed();
        System.out.println("after……");
        return obj;
    }
}
// 3 最后,再MyBatis配置文件里面配置插件
<plugins>
    <plugin interceptor="xxx.MyPlugin">
       <property name="dbType",value="mysql"/>
    </plugin>
</plugins>

分页插件

MyBatis分页实现

MyBatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的原理

  • 分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,拦截Executor的query方法
  • 在执行查询的时候,拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
  • 举例:select * from student,拦截sql后重写为:select t.* from (select * from student) t limit 0, 10

MyBatis通用分页拦截器.png