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