这篇主要看的是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的具体策略数据库
因为变量名太长,没法在流程图中标明链接池状态是如何变化的。有兴趣的能够看下源码。看下源码就能对那些状态变量有了更清晰的认识。apache
怎么才能在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