Mybatis Plugins学习

1、是什么?

mybatis plugin 是一种拦截机制,它允许在特定对象的方法执行之前进行拦截处理,来实现特定的处理功能。

2、用途

  1. 性能监控和日志记录:你可以使用插件来记录SQL执行的时间,以及执行结果,这对于性能调优和问题调试都非常有帮助。MyBatis的插件API非常简单,可以轻松实现这种功能。

  2. 数据加密解密:MyBatis插件可以用来实现数据加密和解密,以保护敏感数据的安全性和完整性。通过插件,可以在数据存储、传输或使用过程中对数据进行加密和解密操作,从而实现数据的保护。

  3. 分页和字段统一赋值: 可以实现自己的分页逻辑以及特殊字段(创建时间、创建人)填充等。

3、使用

MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)

  • ParameterHandler (getParameterObject, setParameters)

  • ResultSetHandler (handleResultSets, handleOutputParameters)

  • StatementHandler (prepare, parameterize, batch, update, query)

通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。

// ExamplePlugin.java
@Intercepts({@Signature(
  type= Executor.class,
  method = "update",
  args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  private Properties properties = new Properties();
  public Object intercept(Invocation invocation) throws Throwable {
    // implement pre processing if need
    Object returnObject = invocation.proceed();
    // implement post processing if need
    return returnObject;
  }
  public void setProperties(Properties properties) {
    this.properties = properties;
  }
}
<!-- mybatis-config.xml -->
<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>

4、拦截原理

通过配置可以知道,在plugins中去配置我们的拦截器,会被解析到configarution对象中去

解析元素到configarution中去,最终保存到interceptorChain拦截链中

InterceptorChain结构

但是,保存之后如何实现对四大对象的拦截呢?

从最基础的mybatis案列开始,获取mapper

经过代理之后执行到查询selectOne()

一直调用下去到doQuery,在这里对我们的statementhandler进行代理拦截

创建RoutingStatementHandler对象的构造函数中会去创建ParameterHandler,ResultSetHandler的代理拦截

调用其父类构造,其中会创建我们的parameterHandler、resultSetHandler

找到了创建的位置后,以其中一个statementhandler为例,看看如何代理,如何拦截。

主要步骤就是循环interceptors,每一个拦截器代理会经历plugin.wrap判断是否代理

1.获取signatureMap

2.获取代理的目标类,即四大对象

3.获取目标类的接口,判断是否在interceptors中声明,如果匹配到目标接口则进行代理。

 回到我们定义的Interceptor实现,每一个@Signature代表我们要拦截的对象接口方法,比如第一个意思代表StatementHandler的query方法,参数是Statement.class、ResultHandler.class类型

调用interceptorChain.pluginAll(statementHandler) 循环嵌套代理,将代理后的类又赋值给target再次代理。

Plugins.wrap实现

获取签名集合,即定义的四个@Signature

 最终解析出StatementHandler.class的(query、update、batch)和Executor.class的(query)方法与我们定义的相同

解析完成后,还需要判断当前的target的接口是否属于其中的一个接口

获取目标类接口

判断是否在signatureMap,如果在,则将接口添加进来,根据匹配的接口数量来判断是否代理。采用JDK动态代理,Plugin为处理器

后续对StatementHandler的所有方法都会执行我们Plugin的invoke方法

从 signatureMap中获取相应对象的方法,如果不为null并且匹配当前方法,则interceptor.intercept,

将目标对象和当前方法包装为 new Invocation(target, method, args)

 最后来到了我们的拦截方法,最后如果是嵌套的代理一定要调用invocation.proceed();这样才会进入到我们的下一个Plugin的invoke()方法

补充:

Executor的代理在openSqlSession的时候

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值