classPooledConnectionimplementsInvocationHandler{@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{StringmethodName=method.getName();// 针对连接的 close() ,进行替换,连接的关闭,修改为将连接归还到连接池。
if(CLOSE.equals(methodName)){dataSource.pushConnection(this);returnnull;}try{// 对于其他方法,逻辑不变,直接执行目标对象的方法。
if(!Object.class.equals(method.getDeclaringClass())){// issue #579 toString() should never fail
// throw an SQLException instead of a Runtime
checkConnection();}returnmethod.invoke(realConnection,args);}catch(Throwablet){throwExceptionUtil.unwrapThrowable(t);}}}
publicclassPooledDataSourceimplementsDataSource{privatePooledConnectionpopConnection(Stringusername,Stringpassword)throwsSQLException{booleancountedWait=false;PooledConnectionconn=null;longt=System.currentTimeMillis();intlocalBadConnectionCount=0;while(conn==null){// 添加同步控制,锁对象是 PoolState。
synchronized(state){// 如果还有空闲连接,则直接从空闲连接中获取一个,获取到的这个连接从空闲连接列表中移除。
if(!state.idleConnections.isEmpty()){// Pool has available connection
conn=state.idleConnections.remove(0);if(log.isDebugEnabled()){log.debug("Checked out connection "+conn.getRealHashCode()+" from pool.");}}else{// 空闲连接列表中,已经没有空闲连接
// 如果当前活跃连接数,小于最大活跃连接数,直接创建新链接。
// Pool does not have available connection
if(state.activeConnections.size()<poolMaximumActiveConnections){// Can create new connection
conn=newPooledConnection(dataSource.getConnection(),this);if(log.isDebugEnabled()){log.debug("Created connection "+conn.getRealHashCode()+".");}}else{// 如果当前活跃链接数,达到了最大活跃连接数,且没有了空闲连接。
// 获取最早创建的连接,判断是否超时
// Cannot create new connection
PooledConnectionoldestActiveConnection=state.activeConnections.get(0);longlongestCheckoutTime=oldestActiveConnection.getCheckoutTime();// 如果已经超时
if(longestCheckoutTime>poolMaximumCheckoutTime){// Can claim overdue connection
// 使用连接超时的次数 +1
state.claimedOverdueConnectionCount++;// 累计超时时间增加。
state.accumulatedCheckoutTimeOfOverdueConnections+=longestCheckoutTime;// 累计的使用连接的时间增加。
state.accumulatedCheckoutTime+=longestCheckoutTime;// 将这个旧的超时连接,从活跃的连接列表中移除。
state.activeConnections.remove(oldestActiveConnection);// 如果这个旧的超时连接,存在尚未完成的事务,进行回滚,如果回滚抛出异常,则忽略异常。
if(!oldestActiveConnection.getRealConnection().getAutoCommit()){try{oldestActiveConnection.getRealConnection().rollback();}catch(SQLExceptione){log.debug("Bad connection. Could not roll back");}}// 没有空闲连接,已达最大活跃连接数,最早的连接已经超时,则在移除超时连接后,创建新的连接。
conn=newPooledConnection(oldestActiveConnection.getRealConnection(),this);conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());// 将旧的超时连接置为无效。
oldestActiveConnection.invalidate();if(log.isDebugEnabled()){log.debug("Claimed overdue connection "+conn.getRealHashCode()+".");}}else{// 没有空闲连接,已达最大活跃连接数,最早的连接没有超时。只能阻塞。
// Must wait
try{if(!countedWait){state.hadToWaitCount++;countedWait=true;}if(log.isDebugEnabled()){log.debug("Waiting as long as "+poolTimeToWait+" milliseconds for connection.");}longwt=System.currentTimeMillis();// 阻塞时间设置为无法取得连接是最大的等待时间。这里的阻塞会释放掉锁,在这期间,有可能会被其他线程唤醒。
state.wait(poolTimeToWait);// 累积等待时间累加上以上阻塞的时间。
state.accumulatedWaitTime+=System.currentTimeMillis()-wt;}catch(InterruptedExceptione){break;}}}}// 如果最终连接不为空。
if(conn!=null){// ping to server and check the connection is valid or not
// 连接有效
if(conn.isValid()){// 真实连接没有自动提交,则回滚掉存在的旧事务。
if(!conn.getRealConnection().getAutoCommit()){conn.getRealConnection().rollback();}conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(),username,password));conn.setCheckoutTimestamp(System.currentTimeMillis());conn.setLastUsedTimestamp(System.currentTimeMillis());// 将获取到的连接放入到活跃连接列表中、请求的次数自增、累积获得连接的时间增加。
state.activeConnections.add(conn);state.requestCount++;state.accumulatedRequestTime+=System.currentTimeMillis()-t;}else{if(log.isDebugEnabled()){log.debug("A bad connection ("+conn.getRealHashCode()+") was returned from the pool, getting another connection.");}// 连接不为空,但是无效。无效连接统计次数自增。
state.badConnectionCount++;localBadConnectionCount++;conn=null;// 如果获取无效连接的次数 大于 最大闲置连接数+最大重试次数,则抛出异常,否则继续尝试获取连接。
if(localBadConnectionCount>(poolMaximumIdleConnections+poolMaximumLocalBadConnectionTolerance)){if(log.isDebugEnabled()){log.debug("PooledDataSource: Could not get a good connection to the database.");}thrownewSQLException("PooledDataSource: Could not get a good connection to the database.");}}}}}if(conn==null){if(log.isDebugEnabled()){log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");}thrownewSQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");}returnconn;}}