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 RuntimecheckConnection();}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 connectionconn=state.idleConnections.remove(0);if(log.isDebugEnabled()){log.debug("Checked out connection "+conn.getRealHashCode()+" from pool.");}}else{// 空闲连接列表中,已经没有空闲连接// 如果当前活跃连接数,小于最大活跃连接数,直接创建新链接。// Pool does not have available connectionif(state.activeConnections.size()<poolMaximumActiveConnections){// Can create new connectionconn=newPooledConnection(dataSource.getConnection(),this);if(log.isDebugEnabled()){log.debug("Created connection "+conn.getRealHashCode()+".");}}else{// 如果当前活跃链接数,达到了最大活跃连接数,且没有了空闲连接。// 获取最早创建的连接,判断是否超时// Cannot create new connectionPooledConnectionoldestActiveConnection=state.activeConnections.get(0);longlongestCheckoutTime=oldestActiveConnection.getCheckoutTime();// 如果已经超时if(longestCheckoutTime>poolMaximumCheckoutTime){// Can claim overdue connection// 使用连接超时的次数 +1state.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 waittry{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;}}