mybatis插件原理初始化过程

插件的目的

让程序员能对SQL参数设置到SQL执行结果返回过程进行扩展, 比如分页插件就是通过对StatementHandler.prepare方法进行拦截,将分页信息拼接到SQL上

原理

利用动态代理对拦截器进行包装,从而实现对所需方法的拦截处理

mybatis插件针对哪几个接口

Executor

执行器,对SqlSession暴露增删改查接口

ParameterHandler

参数处理器,对预编译占位参数进行设值

StatementHandler

SQL执行器,获取statement发送sql执行

ResultHandler

对结果集进行处理

四个接口执行流程

客户端
SqlSessionFactory
SqlSession
Executor
ParameterHandler
StatementHandler
ResultHandler
JDBC驱动

插件如何加载

加载到拦截器链中
InterceptorChain.pluginAll方法
InterceptorChain.pluginAll方法
InterceptorChain.pluginAll方法
InterceptorChain.pluginAll方法
配置文件配置的Interceptor
Configuration.InterceptorChain
Executor
生成代理对象Executor链
ParameterHandler
生成代理对象ParameterHandler链
StatementHandler
生成代理对象StatementHandler链
ResultHandler
生成代理对象ResultHandler链

如何实现一个插件

用分页插件举个例子

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class PaginationInterceptor extends AbstractSqlParserHandler implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
    ......省略
        StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        //内部根据不同的数据拼接指定的分页SQL
        DialectModel model = DialectFactory.buildPaginationSql(page, buildSql, dbType, dialectClazz);
        Configuration configuration = mappedStatement.getConfiguration();
        List<ParameterMapping> mappings = new ArrayList<>(boundSql.getParameterMappings());
        Map<String, Object> additionalParameters = (Map<String, Object>) metaObject.getValue("delegate.boundSql.additionalParameters");
        model.consumers(mappings, configuration, additionalParameters);
        metaObject.setValue("delegate.boundSql.sql", model.getDialectSql());
        metaObject.setValue("delegate.boundSql.parameterMappings", mappings);
        return invocation.proceed();
    }

}

核心注解

@Intercepts

标注此类是一个拦截器

@Signature

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Signature {
  /**
   * 拦截的class类型
   *
   * @return the java type
   */
  Class<?> type();

  /**
   * 拦截的class中的方法名
   *
   * @return the method name
   */
  String method();

  /**
   * 方法所需的参数
   * @return java types for method argument
   */
  Class<?>[] args();
}
posted @   四码难追  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示