/** * Create (if necessary) and return a connection to the database. * * @throws SQLException if a database access error occurs * @return a database connection */ public Connection getConnection() throws SQLException { return createDataSource().getConnection(); }
核心步驟
1.從鏈接池獲取鏈接對象
2.校驗鏈接是否有效數據庫
源碼數據結構
GenericObjectPool性能
public T borrowObject() throws Exception { long starttime = System.currentTimeMillis(); GenericObjectPool.Latch<T> latch = new GenericObjectPool.Latch(); byte whenExhaustedAction; long maxWait; //排隊處理 synchronized(this) { whenExhaustedAction = this._whenExhaustedAction; maxWait = this._maxWait; this._allocationQueue.add(latch); } //從鏈接池獲取鏈接 this.allocate(); while(true) { synchronized(this) { this.assertOpen(); } if (latch.getPair() == null && !latch.mayCreate()) { switch(whenExhaustedAction) { case 0: synchronized(this) { if (latch.getPair() == null && !latch.mayCreate()) { this._allocationQueue.remove(latch); throw new NoSuchElementException("Pool exhausted"); } break; } case 1: try { synchronized(latch) { if (latch.getPair() != null || latch.mayCreate()) { break; } if (maxWait <= 0L) { latch.wait(); } else { long elapsed = System.currentTimeMillis() - starttime; long waitTime = maxWait - elapsed; if (waitTime > 0L) { latch.wait(waitTime); } } } if (this.isClosed()) { throw new IllegalStateException("Pool closed"); } } catch (InterruptedException var51) { boolean doAllocate = false; synchronized(this) { if (latch.getPair() == null && !latch.mayCreate()) { this._allocationQueue.remove(latch); } else if (latch.getPair() == null && latch.mayCreate()) { --this._numInternalProcessing; doAllocate = true; } else { --this._numInternalProcessing; ++this._numActive; this.returnObject(latch.getPair().getValue()); } } if (doAllocate) { this.allocate(); } Thread.currentThread().interrupt(); throw var51; } if (maxWait <= 0L || System.currentTimeMillis() - starttime < maxWait) { continue; } synchronized(this) { if (latch.getPair() != null || latch.mayCreate()) { break; } this._allocationQueue.remove(latch); } throw new NoSuchElementException("Timeout waiting for idle object"); case 2: synchronized(this) { if (latch.getPair() == null && !latch.mayCreate()) { this._allocationQueue.remove(latch); ++this._numInternalProcessing; } break; } default: throw new IllegalArgumentException("WhenExhaustedAction property " + whenExhaustedAction + " not recognized."); } } boolean newlyCreated = false; if (null == latch.getPair()) { boolean var36 = false; try { var36 = true; T obj = this._factory.makeObject(); latch.setPair(new ObjectTimestampPair(obj)); newlyCreated = true; var36 = false; } finally { if (var36) { if (!newlyCreated) { synchronized(this) { --this._numInternalProcessing; } this.allocate(); } } } if (!newlyCreated) { synchronized(this) { --this._numInternalProcessing; } this.allocate(); } } //校驗鏈接是否有效 try { this._factory.activateObject(latch.getPair().value); // if (this._testOnBorrow && !this._factory.validateObject(latch.getPair().value)) { //校驗鏈接是否有效 throw new Exception("ValidateObject failed"); } synchronized(this) { --this._numInternalProcessing; ++this._numActive; } //返回鏈接對象 return latch.getPair().value; //返回鏈接對象 } catch (Throwable var47) { PoolUtils.checkRethrow(var47); try { this._factory.destroyObject(latch.getPair().value); } catch (Throwable var42) { PoolUtils.checkRethrow(var42); } synchronized(this) { --this._numInternalProcessing; if (!newlyCreated) { latch.reset(); this._allocationQueue.add(0, latch); } } this.allocate(); if (newlyCreated) { throw new NoSuchElementException("Could not create a validated object, cause: " + var47.getMessage()); } } } }
真正獲取鏈接對象的是這個方法this
private CursorableLinkedList<ObjectTimestampPair<T>> _pool; //鏈接池,是一個LinkedList //從鏈接池獲取鏈接 private synchronized void allocate() { if (!this.isClosed()) { GenericObjectPool.Latch latch; //封裝了鏈接對象 while(!this._pool.isEmpty() && !this._allocationQueue.isEmpty()) { latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst(); //從排隊裏獲取一個進行處理 latch.setPair((ObjectTimestampPair)this._pool.removeFirst()); //從鏈接池獲取鏈接對象 ++this._numInternalProcessing; synchronized(latch) { latch.notify(); } } while(!this._allocationQueue.isEmpty() && (this._maxActive < 0 || this._numActive + this._numInternalProcessing < this._maxActive)) { latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst(); latch.setMayCreate(true); ++this._numInternalProcessing; synchronized(latch) { latch.notify(); } } } }
public boolean validateObject(Object obj) { if (obj instanceof Connection) { try { this.validateConnection((Connection)obj); //校驗鏈接是否有效 return true; //若是鏈接有效,就返回true } catch (Exception var3) { return false; //若是鏈接無效,就返回false } } else { return false; } }
public void validateConnection(Connection conn) throws SQLException { String query = this._validationQuery; if (conn.isClosed()) { //鏈接已經關閉 throw new SQLException("validateConnection: connection closed"); } else { //鏈接沒有關閉,就校驗鏈接是否有效:經過查詢數據庫,來校驗鏈接是否有效 if (null != query) { Statement stmt = null; ResultSet rset = null; try { stmt = conn.createStatement(); if (this._validationQueryTimeout > 0) { stmt.setQueryTimeout(this._validationQueryTimeout); } rset = stmt.executeQuery(query); if (!rset.next()) { throw new SQLException("validationQuery didn't return a row"); } } finally { if (rset != null) { try { rset.close(); } catch (Exception var14) { } } if (stmt != null) { try { stmt.close(); } catch (Exception var13) { } } } } } }
封裝了鏈接對象spa
private static final class Latch<T> { private ObjectTimestampPair<T> _pair;
static class ObjectTimestampPair<T> implements Comparable<T> { /** @deprecated */ @Deprecated T value; //鏈接對象 /** @deprecated */ @Deprecated long tstamp;
private CursorableLinkedList<ObjectTimestampPair<T>> _pool; //是一個集合,元素是鏈接對象
獲取鏈接的時候,有鎖code
private synchronized void allocate() { //同步方法 if (!this.isClosed()) { GenericObjectPool.Latch latch; while(!this._pool.isEmpty() && !this._allocationQueue.isEmpty()) { latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst(); latch.setPair((ObjectTimestampPair)this._pool.removeFirst()); ++this._numInternalProcessing; synchronized(latch) { latch.notify(); } } while(!this._allocationQueue.isEmpty() && (this._maxActive < 0 || this._numActive + this._numInternalProcessing < this._maxActive)) { latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst(); latch.setMayCreate(true); ++this._numInternalProcessing; synchronized(latch) { latch.notify(); } } } }
一、獲取鏈接對象
對象
真正獲取鏈接對象的方法
blog
二、校驗鏈接是否有效
rem
dbcp是基於pool,底層的鏈接池都是pool實現的。get