侧边栏壁纸
博主头像
DJ's Blog博主等级

行动起来,活在当下

  • 累计撰写 133 篇文章
  • 累计创建 51 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

【Mybatis】插件

Administrator
2022-04-03 / 0 评论 / 0 点赞 / 69 阅读 / 3942 字

【Mybatis】插件

参考:https://mybatis.org/mybatis-3/zh/configuration.html#plugins

使用方式

编写自己的插件类

@Intercepts({ @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class}) })
public class SQLInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        ……
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
        ……
    }
}
  1. 实现Interceptor接口
  2. 添加@Intercepts({@Signature()}),指定拦截的对象和方法、方法参数
  3. 实现接口的3个方法:
// 用于覆盖被拦截对象的原有方法(在调用代理对象Plugin的invoke()方法时被调用)
Object intercept(Invocation invocation) throws Throwable;
// target 是被拦截对象,这个方法的作用是给被拦截对象生成一个代理对象,并返回它
Object plugin(Object target);
// 设置参数
void setProperties(Properties properties);

在mybatis配置文件中注册插件

 <!-- 插件 -->
 <plugins>
     <plugin interceptor="com.gupaoedu.interceptor.SQLInterceptor">
         <property name="gupao" value="betterme"/>
     </plugin>
     <plugin interceptor="com.gupaoedu.interceptor.MyPageInterceptor">
     </plugin>
 </plugins>

插件的执行顺序和定义顺序相反,如上定义,先执行MyPageInterceptor再执行SQLInterceptor

流程

原理

动态代理

允许代理(拦截)的对象和方法

代理(拦截)时机

  • Executor: openSession()方法的时候,executor = (Executor) interceptorChain.pluginAll(executor);
  • StatementHandler:doQuery方法的时候,statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
  • ParameterHandler:doQuery方法的时候,parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
  • ResultSetHandler:doQuery方法的时候,resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);

代理(拦截)顺序

代理类(Plugin)

  • return Plugin.wrap(target, this);返回代理对象
  • 调用invoke()方法执行代理方法,其中会调用拦截器的intercept()方法
  • 调用invocation的proceed()方法返回到被代理对象被拦截的地方

总结

责任链

  • 插件的层层拦截(代理)

举例

PageHelper

应用场景

作业

  • 在未启用日志组件的情况下,输出执行的完整SQL(先实现查询的拦截),并且统计SQL的执行时间
  • 当我们传入RowBounds做翻页查询的时候,使用limit物理分页,代替原来的逻辑分页。
0

评论区