GitHub: MyBatis-PageHelper-源码解说 源码仓库: https://github.com/pagehelper/Mybatis-PageHelper 克隆:git clone https://github.com/pagehelper/Mybatis-PageHelper.git 切分支(tag):git checkout master JDK: 17 参考:com.github.pagehelper.test.reasonable.PageTest     @Test public  void  testMapperWithStartPage ( )  { SqlSession  sqlSession =  MybatisReasonableHelper . getSqlSession ( ) ; UserMapper  userMapper =  sqlSession. getMapper ( UserMapper . class ) ; try  { PageHelper . startPage ( 4 ,  50 ) ;                 List < User > =  userMapper. selectAll ( ) ;    PageInfo < User > =  new  PageInfo < User > ( list) ; } } 
hsqldb\mybatis-config-reasonable.xml< configuration> < plugins> < plugininterceptor = " com.github.pagehelper.PageInterceptor" > < propertyname = " reasonable" value = " true" /> </ plugin> </ plugins> </ configuration> < mappernamespace = " com.github.pagehelper.mapper.UserMapper" > < selectid = " selectAll" resultType = " User" > </ select> </ mapper> com.github.pagehelper.PageHelper
public  class  PageHelper  extends  PageMethod  implements  Dialect ,  BoundSqlInterceptor. Chain  { @Override public  void  afterAll ( )  { AbstractHelperDialect  delegate =  autoDialect. getDelegate ( ) ; if  ( delegate !=  null )  { delegate. afterAll ( ) ; autoDialect. clearDelegate ( ) ; } clearPage ( ) ;     } public  static  void  clearPage ( )  { LOCAL_PAGE . remove ( ) ; } 
} 
com.github.pagehelper.page.PageMethodpublic  abstract  class  PageMethod  { protected  static  final  ThreadLocal < Page > LOCAL_PAGE     =  new  ThreadLocal < Page > ( ) ; protected  static        boolean            DEFAULT_COUNT  =  true ; public  static  < E > Page < E > startPage ( int  pageNum,  int  pageSize)  { return  startPage ( pageNum,  pageSize,  DEFAULT_COUNT ) ;  } public  static  < E > Page < E > startPage ( int  pageNum,  int  pageSize,  boolean  count)  { return  startPage ( pageNum,  pageSize,  count,  null ,  null ) ; } public  static  < E > Page < E > startPage ( int  pageNum,  int  pageSize,  boolean  count,  Boolean  reasonable,  Boolean  pageSizeZero)  { Page < E > =  new  Page < E > ( pageNum,  pageSize,  count) ; page. setReasonable ( reasonable) ;      page. setPageSizeZero ( pageSizeZero) ;  . . . setLocalPage ( page) ; return  page; } public  static  void  setLocalPage ( Page  page)  { LOCAL_PAGE . set ( page) ; } 
} 
com.github.pagehelper.PageInterceptor@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  { private  volatile      Dialect     dialect; private               String      default_dialect_class =  "com.github.pagehelper.PageHelper" ; @Override  public  void  setProperties ( Properties  properties)  { . . . String  dialectClass =  . . .  default_dialect_class;     Dialect  tempDialect =  ClassUtil . newInstance ( dialectClass,  properties) ; tempDialect. setProperties ( properties) ; . . . dialect =  tempDialect; } @Override public  Object  intercept ( Invocation  invocation)  throws  Throwable  { try  { Object [ ]  args =  invocation. getArgs ( ) ; MappedStatement  ms =  ( MappedStatement )  args[ 0 ] ; . . . if  ( args. length ==  4 )  {  . . . }  else  {                 . . . } . . . List  resultList; if  ( ! dialect. skip ( ms,  parameter,  rowBounds) )  {  . . . if  ( dialect. beforeCount ( ms,  parameter,  rowBounds) )  { . . .  else  { Long  count =  count ( executor,  ms,  parameter,  rowBounds,  null ,  boundSql) ; if  ( ! dialect. afterCount ( count,  parameter,  rowBounds) )  {  return  dialect. afterPage ( new  ArrayList ( ) ,  parameter,  rowBounds) ; } } } resultList =  ExecutorUtil . pageQuery (  dialect,  executor,  ms,  parameter,  rowBounds,  resultHandler,  boundSql,  cacheKey) ; . . .  }  . . .  return  dialect. afterPage ( resultList,  parameter,  rowBounds) ;  }  finally  { if  ( dialect !=  null )  { dialect. afterAll ( ) ;  } } } 
} 
原理总体较简单 只在一个拦截器里处理(统计与数据查询) 最后返回 Page<T> 封装集合类