说说Mybatis的插件运行原理,如何编写一个插件?

插件的运行原理?

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

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

mybatis-c487f77a-9b87-4d9b-9a49-5aa87401b5e8.png

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

如何编写一个插件?

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

  • 实现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;
    }
}
  • 然后再给插件编写注解,确定要拦截的对象,要拦截的方法
@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;
    }
}
  • 最后,再MyBatis配置文件里面配置插件
<plugins>
    <plugin interceptor="xxx.MyPlugin">
       <property name="dbType",value="mysql"/>
    </plugin>
</plugins>    

标签: java, Java面试题, mybatis, Java问题合集, Java编程, Java问题精选, Java常见问题, MyBatis面试题