mybatis分页插件PageHelper源码浅析

 

 

PageHelper 是Mybaties中的一个分页插件。其maven坐标 git

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>

目前以更新到5.1 ,新的版本好像和之前的版本有些差异 这里分析下之前的版本 github

<dependency>
     <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.1.3</version>
 </dependency>

其和Mybaties的配置整合不累赘。只看看如何实现分页的原理。sql

先说若是在代码中使用 ,很简单以下,一行代码 ,在查询的时候就自动实现分页:缓存

PageHelper.startPage(params.getPageIndex(), params.getPageSize(), true, true);

其startPage方法重载 :curl

 

跟踪代码 进入到PageHelper这个类 看到这个类继承了Interceptor 接口,这个接口是Mybaties 提供的maven

public class PageHelper implements Interceptor { //sql工具类
    private SqlUtil sqlUtil; //属性参数信息
    private Properties properties; //配置对象方式
    private SqlUtilConfig sqlUtilConfig; //自动获取dialect,若是没有setProperties或setSqlUtilConfig,也能够正常进行
    private boolean autoDialect = true; //运行时自动获取dialect
    private boolean autoRuntimeDialect; //多数据源时,获取jdbcurl后是否关闭数据源
    private boolean closeConn = true; //缓存
    private Map<String, SqlUtil> urlSqlUtilMap = new ConcurrentHashMap<String, SqlUtil>();
  ...
public interface Interceptor {  Object intercept(Invocation invocation) throws Throwable; Object plugin(Object target); void setProperties(Properties properties); }
能够看到 Interceptor 类中有个拦截方法intercept ,这个方法就应该是拦截器的执行方法 。继续跟踪这个方法在哪里有引用 。发现只在类plugin类有引用 

能够看到在method.invoke 执行以前 ,拦截器执行了拦截方法 ,而 pageHelper这个类就是个拦截器 。再看看Plugin这个类 实现了动态代理 的接口 InvocationHandler 。其私有构造方法在静态方法wrap中调用 ,说明这能经过wrap这个方法获取Plugin实例,wrap方法对参数target作了个动态代理 。因此说target执行方法是经过代理 Plugin 执行invoke方法 。工具

那么wrap方法中的target 又是什么呢 ???。wrap方法又是在何时调用的呢 ?一层一层的跟踪 以下代码 。url

 

 又回到了 pageHelp 这个类,在类plugin方法中调用了wrap方法,并且target只有在属于Executor 的时候把target作了代理。跟踪代码发现Plugin方法又在拦截器链InterceptorChain方法pluginAll调用spa

 

 pluginAll 就是把target这个类按拦截器的数量作了屡次对plugin的代理 ,而每一个plugin中都有一个不一样的拦截器 Interceptor。而target在这能够把它 看作是执行器Executor 了 。由于前面说过只对Executor 拦截,再看看pluginAll方法的引用, 在类 Configuration以下插件

 

 能够看到在Configuration建立  Executor 、ParameterHandler、ResultSetHandler、StatementHandler 都有对作代理 ,对拦截器进行拦截执行。可是pageHelp只对Executor 作了代理 。回过头来看看拦截器PageHelp作了什么 ?

/** * Mybatis拦截器方法 * * @param invocation 拦截器入参 * @return 返回执行结果 * @throws Throwable 抛出异常 */
    public Object intercept(Invocation invocation) throws Throwable { if (autoRuntimeDialect) { SqlUtil sqlUtil = getSqlUtil(invocation); return sqlUtil.processPage(invocation); } else { if (autoDialect) { initSqlUtil(invocation); } return sqlUtil.processPage(invocation); } }

方法最终就是经过sqlUtil在执行sql中加了分页参数  。完成分页 。

相关文章
相关标签/搜索