這篇主要看的是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