浅析mybatis源码(二)链接池

这篇主要看的是mybatis对于数据库链接池的实现。实现类为org.apache.ibatis.datasource.pooled包下的PooledDataSource类。 数据库链接池的代码并不难,关键在于理解他的链接和释放的策略。java

链接池参数

protected int poolMaximumActiveConnections = 10;//最大存活链接数,有请求的链接
  protected int poolMaximumIdleConnections = 5;//最大空闲链接数,就是没有处理请求的链接
  protected int poolMaximumCheckoutTime = 20000;//强制收回时间
  protected int poolTimeToWait = 20000;//获取链接等待时间
  protected int poolMaximumLocalBadConnectionTolerance = 3;//若是获取到的是一个坏的链接,那么从新获取一个新的链接,次数最多为 poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance
  protected String poolPingQuery = "NO PING QUERY SET";//心跳查询sql
  protected boolean poolPingEnabled;//容许心跳查询
  protected int poolPingConnectionsNotUsedFor;//执行心跳查询频率

还有一个属性poolState用来存放数据库状态,来看看状态类PoolState的属性sql

链接池状态类属性

protected final List<PooledConnection> idleConnections = new ArrayList<PooledConnection>();//空闲链接列表
  protected final List<PooledConnection> activeConnections = new ArrayList<PooledConnection>();//活跃链接列表
  protected long requestCount = 0;//获取到有效链接的次数
  protected long accumulatedRequestTime = 0;//获取到有效链接的总耗时
  protected long accumulatedCheckoutTime = 0;//收回链接的总耗时
  protected long claimedOverdueConnectionCount = 0;//强制获取链接次数
  protected long accumulatedCheckoutTimeOfOverdueConnections = 0;//强制收回链接占用时间之和
  protected long accumulatedWaitTime = 0;//等待链接收回时间之和
  protected long hadToWaitCount = 0;//等待的请求数量
  protected long badConnectionCount = 0;//坏链接数量

链接池最重要的两个方法莫过于获取链接和释放链接。在池中pop和push则须要根据链接池参数来进行决策。而每次动做都会更新响应的状态。接下来看看pop和push的具体策略数据库

pop策略

push策略

因为变量名太长,没法在流程图中标明链接池状态是如何变化的。有兴趣的能够看下源码。看下源码就能对那些状态变量有了更清晰的认识。apache

PooledConnection类

怎么才能在close的时候不是真的close而是调用pushConnection呢?有一种方式就是使用代理。静态代理相对麻烦,须要把除了close方法外全部方法委托给真实的Connection类。mybatis使用的是动态代理。mybatis

@Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    String methodName = method.getName();
    if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) {//如果close方法
      dataSource.pushConnection(this);
      return null;
    } else {
      try {
        if (!Object.class.equals(method.getDeclaringClass())) {//若是不是Object定义的那些方法
          checkConnection();//检查链接是否有效
        }
        return method.invoke(realConnection, args);//其余方法委托给realConnection
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
  }

总结

链接池的代码并不难,可是能够给咱们一个启发,当使用mybatis链接池遇到问题时或者须要优化、监控等,能够获取到poolState的各个属性,来作一些参考。ide

相关文章
相关标签/搜索