spring mybatis3,接口调用,pagerHelper

Posted 672530440

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring mybatis3,接口调用,pagerHelper相关的知识,希望对你有一定的参考价值。

接口调用: http://localhost:8080/testBoot/getUser/25:

public String GetUser(@PathVariable int id){
        return userMapper.Sel(id).toString();    //userMapper = org.apache.ibatis.binding.MapperProxy。jdk动态代理。
    }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
            if (method.getDeclaringClass() != DecoratingProxy.class) { 
                target = targetSource.getTarget();   //org.apache.ibatis.binding.MapperProxy@357ba95
                Class<?> targetClass = target != null ? target.getClass() : null;
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);   //method = public abstract com.example.entity.User com.example.mapper.UserMapper.Sel(int),返回
                if (chain.isEmpty()) { 
                } else {
                    MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    retVal = invocation.proceed();
                }
        }  
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try { 
    final MapperMethod mapperMethod = cachedMapperMethod(method);   //com.example.mapper.UserMapper.Sel就是调用的方法,
    return mapperMethod.execute(sqlSession, args);    //sqlSession = SQLSessionTemplate
  }
public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
      case INSERT: { 
      }
      case UPDATE: { 
      }
      case DELETE: { 
      }
      case SELECT: 
        } else {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);     //command.getName() = com.example.mapper.UserMapper.Sel,param = 25,sqlSession = SQLSessionTemplate
        }
        break;
      case FLUSH:
        result = sqlSession.flushStatements();
        break;   }
    return result;
  }
SqlSessionTemplate类:
public <T> T selectOne(String statement, Object parameter) {
    return this.sqlSessionProxy.<T> selectOne(statement, parameter);   // statement = com.example.mapper.UserMapper.Sel,parameter = 25。this.sqlSessionProxy = (SqlSession) newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class },
        new SqlSessionInterceptor());   动态代理,先去执行SqlSessionInterceptor的invoke方法,在invoke方法里面去执行真正的方法。
  }
sqlSessionProxy的selectOne方法,selectOne是一个动态代理,最后调到SqlSessionInterceptor类的invoke方法:
private class SqlSessionInterceptor implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,SqlSessionTemplate.this.executorType,SqlSessionTemplate.this.exceptionTranslator);  //返回DefaultSqlSession,
      try {
        Object result = method.invoke(sqlSession, args);       //动态代理真正方法的执行
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { 
          sqlSession.commit(true);    //提交,不是这里提交的,已经提交了。
        }
        return result;
      }  finally {
        if (sqlSession != null) {
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);    //关闭连接
        }
      }
    }
  }
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {  
    session = sessionFactory.openSession(executorType);//没有使用连接池,每次都会创建和销毁SqlSession
    registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
    return session;
  }
DefaultSqlSessionFactory类:
public SqlSession openSession(ExecutorType execType) {
    return openSessionFromDataSource(execType, null, false);
  }
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);    //第一个过滤器
      return new DefaultSqlSession(configuration, executor, autoCommit);
    }   
  }
public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
    return new SpringManagedTransaction(dataSource);
  }
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { 
    Executor executor;
    if (ExecutorType.BATCH == executorType) { 
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);   //SimpleExecutor外面包装一层CachingExecutor,过滤器。
    }
    executor = (Executor) interceptorChain.pluginAll(executor);   //返回的是一个代理。
    return executor;
  }
public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {   //插件,pagerhelper插件,PageInterceptor
      target = interceptor.plugin(target);
    }
    return target;
  }
PageInterceptor类:
public Object plugin(Object target) {
        //TODO Spring bean 方式配置时,如果没有配置属性就不会执行下面的 setProperties 方法,就不会初始化,因此考虑在这个方法中做一次判断和初始化 
        return Plugin.wrap(target, this);    //target = CachingExecutor,this = PageInterceptor
    }
public static Object wrap(Object target, Interceptor interceptor) {
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
    Class<?> type = target.getClass();    //class org.apache.ibatis.executor.CachingExecutor
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));    //target = org.apache.ibatis.executor.CachingExecutor,里面delegate=SimpleExecutor,interceptor = PageInterceptor。返回一个动态代理。
    }
    return target;
  }
 //插件,pagerhelper插件,PageInterceptor
getBean(userMapper)之后,再去getBean(com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration);时候。get这2个bean是独立的没有影响的。
getBean(com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration);
exposedObject = initializeBean(beanName, exposedObject, mbd);    //beanName = com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); //beanName = com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
PageHelperAutoConfiguration类:
public void addPageInterceptor() {
        PageInterceptor interceptor = new PageInterceptor(); 
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            sqlSessionFactory.getConfiguration().addInterceptor(interceptor);   
        }
    }
public void addInterceptor(Interceptor interceptor) {
    interceptorChain.addInterceptor(interceptor);    //把pagehelper加到拦截器,所以上面interceptors就有这个pagehelper了。
  }
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }

Object result = method.invoke(sqlSession, args);

public <T> T selectOne(String statement, Object parameter) { 
    List<T> list = this.<T>selectList(statement, parameter);  //statement = com.example.mapper.UserMapper.Sel,parameter = 25
    if (list.size() == 1) {
      return list.get(0);   //com.example.entity.User@7d592c2e
    }  
  }

public <E> List<E> selectList(String statement, Object parameter) {
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
  }
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);    //拦截器开始执行。org.apache.ibatis.executor.CachingExecutor
    } 
  }
Plugin类:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    //proxy = org.apache.ibatis.executor.CachingExecutor,
    try {
      Set<Method> methods = signatureMap.get(method.getDeclaringClass());
      if (methods != null && methods.contains(method)) {
        return interceptor.intercept(new Invocation(target, method, args));    //interceptor = PageInterceptor,target = CachingExecutor,
      } 
    } 
  }
PageInterceptor类:
public Object intercept(Invocation invocation) throws Throwable {
        try {
            Object[] args = invocation.getArgs();
            MappedStatement ms = (MappedStatement) args[0];
            Object parameter = args[1];
            RowBounds rowBounds = (RowBounds) args[2];
            ResultHandler resultHandler = (ResultHandler) args[3];
            Executor executor = (Executor) invocation.getTarget();    //target = CachingExecutor,
            CacheKey cacheKey;
            BoundSql boundSql;
            //由于逻辑关系,只会进入一次
            if(args.length == 4){
                //4 个参数时
                boundSql = ms.getBoundSql(parameter);    //select * from money where id = ?
                cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);    //executor = CachingExecutor,返回//868805043:3351384746:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
            } else {
                //6 个参数时
                cacheKey = (CacheKey) args[4];
                boundSql = (BoundSql) args[5];
            }
            List resultList;
            //调用方法判断是否需要进行分页,如果不需要,直接返回结果
            if (!dialect.skip(ms, parameter, rowBounds)) {
                //反射获取动态参数
                String msId = ms.getId();    //com.example.mapper.UserMapper.Sel
                Configuration configuration = ms.getConfiguration();   
                Map<String, Object> additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
                //判断是否需要进行 count 查询
                if (dialect.beforeCount(ms, parameter, rowBounds)) {
                    String countMsId = msId + countSuffix;    //com.example.mapper.UserMapper.Sel_COUNT
                    Long count;
                    //先判断是否存在手写的 count 查询
                    MappedStatement countMs = getExistedMappedStatement(configuration, countMsId);
                    if(countMs != null){
                        count = executeManualCount(executor, countMs, parameter, boundSql, resultHandler);
                    } else {
                        countMs = msCountMap.get(countMsId);
                        //自动创建
                        if (countMs == null) { 
                        }
                        count = executeAutoCount(executor, countMs, parameter, boundSql, rowBounds, resultHandler); //返回1,只有一条数据,先查询总数,
                    }
                    //处理查询总数
                    //返回 true 时继续分页查询,false 时直接返回。查询count=0就不用查询了。
                    if (!dialect.afterCount(count, parameter, rowBounds)) {
                        //当查询总数为 0 时,直接返回空的结果。
                        return dialect.afterPage(new ArrayList(), parameter, rowBounds);
                    }
                }
                //判断是否需要进行分页查询
                if (dialect.beforePage(ms, parameter, rowBounds)) {
                    //生成分页的缓存 key
                    CacheKey pageKey = cacheKey;  //868805043:3351384746:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
                    //处理参数对象
                    parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey);    //{First_PageHelper=0, Second_PageHelper=2, id=25}
                    //调用方言获取分页 sql
                    String pageSql = dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey);   //select * from money where id = ? LIMIT ? 
                    BoundSql pageBoundSql = new BoundSql(configuration, pageSql, boundSql.getParameterMappings(), parameter);     //select * from money where id = ? LIMIT ? 
                    //设置动态参数
                    for (String key : additionalParameters.keySet()) {
                        pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
                    }
                    //执行分页查询
                    resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);    //先执行查询总数,在是真正的查询。 //com.example.entity.User@7d592c2e,物理分页。
                } else {
                    //不执行分页的情况下,也不执行内存分页
                    resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql);
                }
            } else {
                //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
                resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
            }
            return dialect.afterPage(resultList, parameter, rowBounds);
        } finally {
            dialect.afterAll();
        }
    }
public Object afterPage(List pageList, Object parameterObject, RowBounds rowBounds) {
        //这个方法即使不分页也会被执行,所以要判断 null
        AbstractHelperDialect delegate = autoDialect.getDelegate();
        if(delegate != null){
            return delegate.afterPage(pageList, parameterObject, rowBounds);
        }
        return pageList;
    }
public Object afterPage(List pageList, Object parameterObject, RowBounds rowBounds) {
        Page page = getLocalPage();
        if (page == null) {
            return pageList;
        }
        page.addAll(pageList);
        if (!page.isCount()) {
            page.setTotal(-1);
        } else if ((page.getPageSizeZero() != null && page.getPageSizeZero()) && page.getPageSize() == 0) {
            page.setTotal(pageList.size());
        } else if(page.isOrderByOnly()){
            page.setTotal(pageList.size());
        }
        return page;
    }
CachingExecutor类:
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);   //delegate = SimpleExecutor
  }
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) { 
    CacheKey cacheKey = new CacheKey();
    cacheKey.update(ms.getId());
    cacheKey.update(rowBounds.getOffset());
    cacheKey.update(rowBounds.getLimit());
    cacheKey.update(boundSql.getSql());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHa 
    return cacheKey; //868805043:3351384746:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
  }
private Long executeAutoCount(Executor executor, MappedStatement countMs,
                                   Object parameter, BoundSql boundSql,
                                   RowBounds rowBounds, ResultHandler resultHandler) throws IllegalAccessException, SQLException {
        Map<String, Object> additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
        //创建 count 查询的缓存 key
        CacheKey countKey = executor.createCacheKey(countMs, parameter, RowBounds.DEFAULT, boundSql);    //executor = CachingExecutor,返回-888539805:2639554458:com.example.mapper.UserMapper.Sel_COUNT:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
        //调用方言获取 count sql
        String countSql = dialect.getCountSql(countMs, boundSql, parameter, rowBounds, countKey);    //SELECT count(0) FROM money WHERE id = ?
        //countKey.update(countSql);
        BoundSql countBoundSql = new BoundSql(countMs.getConfiguration(), countSql, boundSql.getParameterMappings(), parameter);    //SELECT count(0) FROM money WHERE id = ?
        //当使用动态 SQL 时,可能会产生临时的参数,这些参数需要手动设置到新的 BoundSql 中
        for (String key : additionalParameters.keySet()) {
            countBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
        }
        //执行 count 查询
        Object countResultList = executor.query(countMs, parameter, RowBounds.DEFAULT, resultHandler, countKey, countBoundSql); //executor = CachingExecutor, //返回1,只有一条数据
        Long count = (Long) ((List) countResultList).get(0);
        return count;
    }
CachingExecutor类:
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    Cache cache = ms.getCache();
    if (cache != null) {   //缓存没用到,mybtis的缓存不要用。缓存都是对查询语句缓存,
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, boundSql);
        @SuppressWarnings("unchecked")
        List<E> list = (List<E>) tcm.getObject(cache, key);
        if (list == null) {
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);   //delegate = SimpleExecutor
  }
SimpleExecutor父类BaseExecutor:
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());    //ms.getResource() = file [E:CodemybatisspringBoot_Mybatis-masterspringBoot_Mybatis-masterSpringboot_Mybatis	argetclassesmappingUserMapper.xml],
ms.getId() = com.example.mapper.UserMapper.Sel_COUNT 
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;    //key = -888539805:2639554458:com.example.mapper.UserMapper.Sel_COUNT:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); //com.example.entity.User@7d592c2e
      }
    } finally {
      queryStack--;
    } 
    return list;
  }
SimpleExecutor父类BaseExecutor:
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);    //加入到缓存,
    try {
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);   //返回1,只有一条数据, //com.example.entity.User@7d592c2e
    } finally {
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);//{1346928873:3351384750:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:      SqlSessionFactoryBean:0:2:2=[com.example.entity.User@7d592c2e], -888539805:2639554458:com.example.mapper.UserMapper.Sel_COUNT:0:2147483647:select * from money where id = ?:25:      SqlSessionFactoryBean=[1]}  缓存。
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);    //设置sql语句里面的?对应的值。
    return stmt;
  }
protected Connection getConnection(Log statementLog) throws SQLException {
    Connection connection = transaction.getConnection();
    if (statementLog.isDebugEnabled()) {
      return ConnectionLogger.newInstance(connection, statementLog, queryStack);    //对connection生成一个动态代理,用于日志打印。
    } else {
      return connection;
    }
  }
public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {
    InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);
    ClassLoader cl = Connection.class.getClassLoader();
    return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
  }
RoutingStatementHandler类:
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    return delegate.prepare(connection, transactionTimeout);
  }
BaseStatementHandler类:
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
      statement = instantiateStatement(connection);
      setStatementTimeout(statement, transactionTimeout);
      setFetchSize(statement);
      return statement;
    } 
  }
protected Statement instantiateStatement(Connection connection) throws SQLException {
    String sql = boundSql.getSql();   //insert into money (id, name, money) values (?, ?, ?)
    if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
      String[] keyColumnNames = mappedStatement.getKeyColumns(); 
    } else {
      return connection.prepareStatement(sql);   //connection是一个动态代理,会去调用ConnectionLogger的invoke方法。
    }
  }
ConnectionLogger类:
public Object invoke(Object proxy, Method method, Object[] params)
      throws Throwable {
    try { 
      if ("prepareStatement".equals(method.getName())) {
        if (isDebugEnabled()) {
          debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);    //打印sql语句,不需要log4J,只需要application-dev.yml配置logging:  level: com: example:  mapper : debug  就可以打印sql语句了。
        }        
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);   //被代理对象的调用,动态代理真正方法的执行,connection的prepareStatement方法。所以这里的动态代理增强就是用于日志打印。
        stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);     //这里又是动态代理增强,就是用于日志打印。
        return stmt; 
  }
public static PreparedStatement newInstance(PreparedStatement stmt, Log statementLog, int queryStack) {
    InvocationHandler handler = new PreparedStatementLogger(stmt, statementLog, queryStack);   //日志打印的动态代理
    ClassLoader cl = PreparedStatement.class.getClassLoader();
    return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);
  }

public void parameterize(Statement statement) throws SQLException {
    delegate.parameterize(statement);  //设置sql语句里面的?对应的值。
  }
public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }
RoutingStatementHandler类:
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    return delegate.<E>query(statement, resultHandler);
  }
PreparedStatementHandler类:
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();   //ps是一个动态代理增强,用于日志打印,就是上面的:Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);所以先去执行PreparedStatementLogger的invoke,然后在invoke方法里面去执行真正的方法调用,
    return resultSetHandler.<E> handleResultSets(ps);  //对结果集的封装,ps是查询的结果。
  }
PreparedStatementLogger类:
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, params);
      }          
      if (EXECUTE_METHODS.contains(method.getName())) { 
        if (isDebugEnabled()) {
          debug("Parameters: " + getParameterValueString(), true);     //打印sql的查询参数,不需要log4J,只需要application-dev.yml配置logging:  level: com: example:  mapper : debug  就可以打印sql语句了。
        }
        clearColumnInfo();
        if ("executeQuery".equals(method.getName())) {
          ResultSet rs = (ResultSet) method.invoke(statement, params);
          return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
        } else {
          return method.invoke(statement, params);   //method = public abstract boolean java.sql.PreparedStatement.execute() ,动态代理真正方法的执行,
        }
      } 
ProxyPreparedStatement类:
public boolean execute() throws SQLException
   {
      connection.markCommitStateDirty();
      return ((PreparedStatement) delegate).execute();   //delegate = com.mysql.cj.jdbc.ClientPreparedStatement: SELECT count(0) FROM money WHERE id = 25
   }
ClientPreparedStatement类:
public boolean execute() throws SQLException {
        try {
            synchronized(this.checkClosed().getConnectionMutex()) {
                JdbcConnection locallyScopedConn = this.connection;   //com.mysql.cj.conf.HostInfo@f6c2c82 :: {host: "localhost", port: 3306, user: root, password: 123456, hostProperties: {dbname=account}}    
                        rs = this.executeInternal(this.maxRows, sendPacket, this.createStreamingResultSet(), ((PreparedQuery)this.query).getParseInfo().getFirstStmtChar() == S, cachedMetadata, false);   //   sendPacket  =    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5  
                        if (rs != null) {
                            this.lastInsertId = rs.getUpdateID();
                            this.results = rs;
                        }
                        return rs != null && rs.hasRows();
                    }
                }
            }
        }  
    }
protected <M extends Message> ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, M sendPacket, boolean createStreamingResultSet, boolean queryIsSelectOnly, ColumnDefinition metadata, boolean isBatch) throws SQLException {
        try {
            synchronized(this.checkClosed().getConnectionMutex()) { 
                try {
                    JdbcConnection locallyScopedConnection = this.connection;    //com.mysql.cj.conf.HostInfo@f6c2c82 :: {host: "localhost", port: 3306, user: root, password: 123456, hostProperties: {dbname=account}}  

                        rs = (ResultSetInternalMethods)((NativeSession)locallyScopedConnection.getSession()).execSQL(this, (String)null, maxRowsToRetrieve, (NativePacketPayload)sendPacket, createStreamingResultSet, this.getResultSetFactory(), this.getCurrentCatalog(), metadata, isBatch); 
                    } finally {  
                    }  

                return var10000;
            }
        }  
    }
public <T extends Resultset> T execSQL(Query callingQuery, String query, int maxRows, NativePacketPayload packet, boolean streamResults, ProtocolEntityFactory<T, NativePacketPayload> resultSetFactory, String catalog, ColumnDefinition cachedMetadata, boolean isBatch) {    
        Resultset var30;
        label222: { 
            try {  
                var13 = ((NativeProtocol)this.protocol).sendQueryPacket(callingQuery, packet, maxRows, streamResults, catalog, cachedMetadata, this::getProfilerEventHandlerInstanceFunction, resultSetFactory);
            } finally {     
    }
NativePacketPayload resultPacket = this.sendCommand(queryPacket, false, 0);  //   sendPacket  =    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5
this.send(queryPacket, queryPacket.getPosition());;  //   queryPacket=    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5
this.packetSender.send(packet.getByteBuffer(), packetLen, this.packetSequence);  //   packet=    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5

public void send(byte[] packet, int packetLen, byte packetSequence) throws IOException {
        this.packetSender.send(packet, packetLen, packetSequence);
        this.previousPacketSentTime = this.lastPacketSentTime;
        this.lastPacketSentTime = System.currentTimeMillis();
    }
public void send(byte[] packet, int packetLen, byte packetSequence) throws IOException {
        PacketSplitter packetSplitter = new PacketSplitter(packetLen);
        while(packetSplitter.nextPacket()) {
            this.outputStream.write(NativeUtils.encodeMysqlThreeByteInteger(packetSplitter.getPacketLen()));
            this.outputStream.write(packetSequence++);
            this.outputStream.write(packet, packetSplitter.getOffset(), packetSplitter.getPacketLen());
        }
        this.outputStream.flush();
    }

对结果集的封装 //把结果集映射成javaBean。

public List<Object> handleResultSets(Statement stmt) throws SQLException {   
    ResultSetWrapper rsw = getFirstResultSet(stmt);   //把PrapareStatment的ResultSet拿出来,并且包装成ResultSetWrapper 

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();  //拿到UserMapper.xml里面的<resultMap>节点,然后做映射。ORM就是做映射。
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    } 

    return collapseSingleResultList(multipleResults);   //multipleResults = [com.example.entity.User(25,JAck,100), com.example.entity.User(27,Kackeeee,100)]
  }
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
    ResultSet rs = stmt.getResultSet();   //返回org.apache.ibatis.logging.jdbc.ResultSetLogger是ResultSet的代理
    return rs != null ? new ResultSetWrapper(rs, configuration) : null;    //把ResultSet包装成ResultSetWrapper
  }
public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException {
    super();
    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.resultSet = rs;   //org.apache.ibatis.logging.jdbc.ResultSetLogger
    final ResultSetMetaData metaData = rs.getMetaData();//
    final int columnCount = metaData.getColumnCount();//3,列的数量
    for (int i = 1; i <= columnCount; i++) {
      columnNames.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i));  //列的名称:[id, name, money]
      jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i)));//列的类型:[INTEGER, VARCHAR, VARCHAR]
      classNames.add(metaData.getColumnClassName(i));//列的类名:[java.lang.Integer, java.lang.String, java.lang.String]
    }
  }
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping)  {
    try {
      if (parentMapping != null) { 
      } else {
        if (resultHandler == null) {
          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
          multipleResults.add(defaultResultHandler.getResultList());  ////查询的多条记录,放到list里面去。[com.example.entity.User(25,JAck,100), com.example.entity.User(27,Kackeeee,100)]
        } else { 
        }
      }
    } 
  }
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)   {
    if (resultMap.hasNestedResultMaps()) {  
    } else {
      handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    }
  }
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)  {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
    skipRows(rsw.getResultSet(), rowBounds);//rowBounds是分页的。Limit是查询几条记录,offset是跳过几天记录。
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap);返回com.example.entity.User(id=25,name=LACK2,money=100)
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());//有可能有多条记录,放到一个list里面去,
    }
  }
private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
    if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
      if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
        rs.absolute(rowBounds.getOffset());
      }
    } else {
      for (int i = 0; i < rowBounds.getOffset(); i++) {
        rs.next();//跳过几条,mybatis的分页是内存分页,因为ResultSet结果集 已经查询出来了。但是加了PageHelper之后,ResultSet 结果集 就是已经分页的,就是物理分页了。
      }
    }
  }
public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
    Set<String> pastDiscriminators = new HashSet<String>();
    Discriminator discriminator = resultMap.getDiscriminator();
    while (discriminator != null) { 
    }
    return resultMap;
  }
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);   //根据resultMap标签的Type创建反射对象class com.example.entity.User。返回com.example.entity.User(id=25,name=LACK2,money=100)
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { 
    }
    return rowValue;
  }
private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
    this.useConstructorMappings = false; // reset previous mapping result
    final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
    final List<Object> constructorArgs = new ArrayList<Object>();
    Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);  //把结果集映射成javaBean。返回com.example.entity.User(id=25,name=LACK2,money=100)。通过反射创建对象和设置值。
    if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); 
    }
    this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result
    return resultObject;
  } 
private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
    if (parentMapping != null) { 
    } else {
      callResultHandler(resultHandler, resultContext, rowValue);
    }
  }
private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
    resultContext.nextResultObject(rowValue);
    ((ResultHandler<Object>) resultHandler).handleResult(resultContext);
  }
public class DefaultResultHandler implements ResultHandler<Object> {  
  @Override
  public void handleResult(ResultContext<? extends Object> context) {
    list.add(context.getResultObject());//查询的多条记录,放到list里面去。
  } 
}

 

以上是关于spring mybatis3,接口调用,pagerHelper的主要内容,如果未能解决你的问题,请参考以下文章

[转]Mybatis3.x与Spring4.x整合

SSM整合:Spring4与Mybatis3整合

spring3.2+mybatis3.2+maven整合

搭建SSM环境——基于Spring4和Mybatis3

Maven3.0+Spring MVC4+Spring 4+Mybatis3+junit4

spring配置mybatis3