Mybatis学习系列(十二):PageHelper分页插件

本文探讨了在Mybatis中使用PageHelper分页插件的原因,它通过插件拦截器链来提高分页效率。PageHelper在创建StatementHandler时包装interceptorChain,并在解析配置文件时通过pluginElement方法初始化interceptors。分页过程涉及Interceptor接口的实现,通过Proxy对象进行方法调用,并按步骤执行分页逻辑,包括dialect选择、count查询、处理总数、分页查询和生成分页SQL。
摘要由CSDN通过智能技术生成

由于mybatis原生的分页是在内存里面进行的,导致效率很低,但是我们在生产项目中有很多的分页需求,这个时候PageHelper分页插件就诞生了。PageHelper主要是通过插件拦截链实现的。

我们知道在创建StatementHandler 的时候,我们包装了interceptorChain链

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }

//给某个对象添加插件拦截器链
public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }

那这里如何初始化interceptors呢?

我们知道在解析配置文件的时候有一个解析plugin的方法:pluginElement(root.evalNode("plugins"));

private void pluginElement(XNode parent) throws Exception {
    if (parent != null) {
      //解析每一个插件拦截器
      for (XNode child : parent.getChildren()) {
        //获取配置信息
        String interceptor = child.getStringAttribute("interceptor");
        Properties properties = child.getChildrenAsProperties();
        Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
        //添加参数
        interceptorInstance.setProperties(properties);
        //添加插件拦截器到configuration中
        configuration.addInterceptor(interceptorInstance);
      }
    }
  }

//添加参数  这里看PageInterceptor
public void setProperties(Properties properties) {
        //缓存 count ms
        msCountMap = CacheFactory.createCache(properties.getProperty("msCountCache"), "ms", properties);
        String dialectClass = properties.getProperty("dialect");
        if (StringUtil.isEmpty(dialectClass)) {
            //这里如果没有配置dialect  走默认的com.github.pagehelper.PageHelper
            dialectClass = default_dialect_class;
        }
        try {
            Class<?> aClass = Class.forName(dialectClass);
            dialect = (Dialect) aClass.newInstance();
        } catch (Exception e) {
            throw new PageException(e);
        }
        dialect.setProperties(properties);

        String countSuffix = properties.getProperty("countSuffix");
        if (StringUtil.isNotEmpty(countSuffix)) {
            this.countSuffix = countSuffix;
        }

        try {
            //反射获取 BoundSql 中的 additionalParameters 属性
            additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters");
            additionalParametersField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            throw new PageException(e);
        }
    }


//添加插件拦截器到configuration中
public void addInterceptor(Interceptor interceptor) {
    interceptorChain.addInterceptor(interceptor);
  }

然后我们看一下pagehelper是如何实现的

@Intercepts(
    {
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
    }
)
public class PageInterceptor implements Interceptor

首先我们发现这里必须是实现了Interceptor接口,这样才可以配置在plugin标签里

然后我们看一下interceptor.plugin(target);方法

public Object plugin(Object target) {
        //TODO Spring bean 方式配置时࿰
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值