示例:
假如配置了PageHelper插件

public class MyBatisTest10 {
    public static void main(String[] args) throws IOException {
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(
                Resources.getResourceAsStream("mybatis-config.xml"));
        
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<Country> countries = sqlSession.getMapper(PersonMapper.class).selectCountry2(1, 2);
        System.out.println(countries.size());
        System.out.println(countries);
    }
}

执行sqlSessionFactory.openSession()时,进入openSession方法,代码如下:

MyBatis: 插件是怎么起作用的?_sql


其中调用的openSessionFromDataSource,其代码如下:

MyBatis: 插件是怎么起作用的?_java_02


其中调用了configuration对象的newExecutor方法,该方法代码如下:

MyBatis: 插件是怎么起作用的?_sql_03


其中调用了interceptorChain对象的pluginAll方法,interceptorChain对象中为我们定义的所有实现了Interceptor接口的类,PageInterceptor就是其中之一。pluginAll方法代码如下:

MyBatis: 插件是怎么起作用的?_mybatis_04


从上图可以看到,这个方法中会遍历所有interceptor,然后调用其plugin方法,PageInterceptor的plugin方法代码如下:

MyBatis: 插件是怎么起作用的?_动态代理_05


其中调用的wrap方法代码如下:

MyBatis: 插件是怎么起作用的?_java_06


该方法位于Plugin类,我们可以看到,它使用了JDK动态代理生成了代理对象。

可见,所有的插件最后都是通过生成动态代理对象来实现其功能的。调用的时候,会调用Plugin类的invoke方法,其代码如下:

MyBatis: 插件是怎么起作用的?_java_07


可以看到,其中调用了interceptor的intercept方法,如果我们配置了PageInterceptor,则会走到PageInterceptor的intercept方法进行执行,该方法代码如下:

MyBatis: 插件是怎么起作用的?_sql_08


MyBatis: 插件是怎么起作用的?_mybatis_09

该方法真正完成了分页查询。来到pageQuery的代码

MyBatis: 插件是怎么起作用的?_sql_10


可以看到其中调用了dialect.getPageSql方法,该方法代码如下:

MyBatis: 插件是怎么起作用的?_sql_11


如果我们的数据库是MySQL,则最后调用getPageSql将来到MySQLDialect类:

MyBatis: 插件是怎么起作用的?_sql_12


在这里我们可以看到了添加limit的相关内容,也就是在原有SQL基础上加了分页功能