mybatis分頁插件PageHelper源碼淺析


 

 

PageHelper 是Mybaties中的一個分頁插件。其maven坐標 

<!-- 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 ,新的版本好像和以前的版本有些差別 這里分析下以前的版本 

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

其和Mybaties的配置整合不累贅。只看看如何實現分頁的原理。

先說如果在代碼中使用 ,很簡單如下,一行代碼 ,在查詢的時候就自動實現分頁:

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

其startPage方法重載 :

 

跟蹤代碼 進入到PageHelper這個類 看到這個類繼承了Interceptor 接口,這個接口是Mybaties 提供的

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方法又是在什么時候調用的呢 ?一層一層的跟蹤 如下代碼 。

 

 又回到了 pageHelp 這個類,在類plugin方法中調用了wrap方法,而且target只有在屬於Executor 的時候把target做了代理。跟蹤代碼發現Plugin方法又在攔截器鏈InterceptorChain方法pluginAll調用

 

 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中加了分頁參數  。完成分頁 。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM