數據庫連接池DBCP源碼剖析
阿新 • • 發佈:2018-03-02
for targe evict 執行 disco 成對 加載數據 swa 行數據
BasicDataSource.getConnection()
public Connection getConnection() throws SQLException { if (Utils.IS_SECURITY_ENABLED) { PrivilegedExceptionAction<Connection> action = new PaGetConnection(); try { return AccessController.doPrivileged(action); }catch (PrivilegedActionException e) { Throwable cause = e.getCause(); if (cause instanceof SQLException) { throw (SQLException) cause; } throw new SQLException(e); } } return createDataSource().getConnection(); }
createDataSource()
} // Return the pool if we have already created it // This is double-checked locking. This is safe since dataSource is // volatile and the code is targeted at Java 5 onwards. if (dataSource != null) { return dataSource; }
//同步方法,防止多線程重復創建數據源synchronized (this) { if (dataSource != null) { return dataSource; } jmxRegister(); // create factory which returns raw physical connections
//創建JDBC連接工廠
ConnectionFactory driverConnectionFactory = createConnectionFactory(); // Set up the poolable connection factory boolean success = false;
//創建連接池工廠 PoolableConnectionFactory poolableConnectionFactory; try { poolableConnectionFactory = createPoolableConnectionFactory( driverConnectionFactory); poolableConnectionFactory.setPoolStatements( poolPreparedStatements); poolableConnectionFactory.setMaxOpenPrepatedStatements( maxOpenPreparedStatements); success = true; } catch (SQLException se) { throw se; } catch (RuntimeException rte) { throw rte; } catch (Exception ex) { throw new SQLException("Error creating connection factory", ex); } if (success) { // create a pool for our connections createConnectionPool(poolableConnectionFactory); } // Create the pooling data source to manage connections DataSource newDataSource; success = false; try { newDataSource = createDataSourceInstance(); newDataSource.setLogWriter(logWriter); success = true; } catch (SQLException se) { throw se; } catch (RuntimeException rte) { throw rte; } catch (Exception ex) { throw new SQLException("Error creating datasource", ex); } finally { if (!success) { closeConnectionPool(); } } // If initialSize > 0, preload the pool
//往連接池添加初始化大小的連接
try { for (int i = 0 ; i < initialSize ; i++) { connectionPool.addObject(); } } catch (Exception e) { closeConnectionPool(); throw new SQLException("Error preloading the connection pool", e); } // If timeBetweenEvictionRunsMillis > 0, start the pool‘s evictor task startPoolMaintenance(); dataSource = newDataSource; return dataSource; } }
createConnectionFactory():創建連接池工廠
protected ConnectionFactory createConnectionFactory() throws SQLException { // Load the JDBC driver class
//加載數據庫驅動
Driver driverToUse = this.driver; if (driverToUse == null) { Class<?> driverFromCCL = null; if (driverClassName != null) { try { try { if (driverClassLoader == null) { driverFromCCL = Class.forName(driverClassName); } else { driverFromCCL = Class.forName( driverClassName, true, driverClassLoader); } } catch (ClassNotFoundException cnfe) { driverFromCCL = Thread.currentThread( ).getContextClassLoader().loadClass( driverClassName); } } catch (Exception t) { String message = "Cannot load JDBC driver class ‘" + driverClassName + "‘"; logWriter.println(message); t.printStackTrace(logWriter); throw new SQLException(message, t); } } try { if (driverFromCCL == null) { driverToUse = DriverManager.getDriver(url); } else { // Usage of DriverManager is not possible, as it does not // respect the ContextClassLoader // N.B. This cast may cause ClassCastException which is handled below driverToUse = (Driver) driverFromCCL.newInstance(); if (!driverToUse.acceptsURL(url)) { throw new SQLException("No suitable driver", "08001"); } } } catch (Exception t) { String message = "Cannot create JDBC driver of class ‘" + (driverClassName != null ? driverClassName : "") + "‘ for connect URL ‘" + url + "‘"; logWriter.println(message); t.printStackTrace(logWriter); throw new SQLException(message, t); } } // Set up the driver connection factory we will use String user = username; if (user != null) { connectionProperties.put("user", user); } else { log("DBCP DataSource configured without a ‘username‘"); } String pwd = password; if (pwd != null) { connectionProperties.put("password", pwd); } else { log("DBCP DataSource configured without a ‘password‘"); } //創建JDBC連接工廠 ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driverToUse, url, connectionProperties); return driverConnectionFactory; }
createPoolableConnectionFactory()
protected PoolableConnectionFactory createPoolableConnectionFactory( ConnectionFactory driverConnectionFactory) throws SQLException { PoolableConnectionFactory connectionFactory = null; try { connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, registeredJmxName); connectionFactory.setValidationQuery(validationQuery); connectionFactory.setValidationQueryTimeout(validationQueryTimeout); connectionFactory.setConnectionInitSql(connectionInitSqls); connectionFactory.setDefaultReadOnly(defaultReadOnly); connectionFactory.setDefaultAutoCommit(defaultAutoCommit); connectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation); connectionFactory.setDefaultCatalog(defaultCatalog); connectionFactory.setCacheState(cacheState); connectionFactory.setPoolStatements(poolPreparedStatements); connectionFactory.setMaxOpenPrepatedStatements(maxOpenPreparedStatements); connectionFactory.setMaxConnLifetimeMillis(maxConnLifetimeMillis); connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); connectionFactory.setEnableAutoCommitOnReturn(getEnableAutoCommitOnReturn()); connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeout()); connectionFactory.setFastFailValidation(fastFailValidation); connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); validateConnectionFactory(connectionFactory); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e); } return connectionFactory; }
createConnectionPool():創建對象池保存活躍連接
protected void createConnectionPool(PoolableConnectionFactory factory) { // Create an object pool to contain our active connections GenericObjectPoolConfig config = new GenericObjectPoolConfig(); updateJmxName(config); config.setJmxEnabled(registeredJmxName != null); // Disable JMX on the underlying pool if the DS is not registered. GenericObjectPool<PoolableConnection> gop; if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow() || abandonedConfig.getRemoveAbandonedOnMaintenance())) { gop = new GenericObjectPool<>(factory, config, abandonedConfig); } else { gop = new GenericObjectPool<>(factory, config); } gop.setMaxTotal(maxTotal); gop.setMaxIdle(maxIdle); gop.setMinIdle(minIdle); gop.setMaxWaitMillis(maxWaitMillis); gop.setTestOnCreate(testOnCreate); gop.setTestOnBorrow(testOnBorrow); gop.setTestOnReturn(testOnReturn); gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun); gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); gop.setTestWhileIdle(testWhileIdle); gop.setLifo(lifo); gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections)); gop.setEvictionPolicyClassName(evictionPolicyClassName); factory.setPool(gop);
//生成對象池 connectionPool = gop; }
從圖中可以看出,由執行器Executor獲取數據庫連接進行數據庫操作的
PoolableConnection.getConnection()
public Connection getConnection() throws SQLException { try {
//從連接池獲取連接 C conn = _pool.borrowObject(); if (conn == null) { return null; } return new PoolGuardConnectionWrapper<>(conn); } catch(SQLException e) { throw e; } catch(NoSuchElementException e) { throw new SQLException("Cannot get a connection, pool error " + e.getMessage(), e); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new SQLException("Cannot get a connection, general error", e); } }
PoolableConnection.close():這裏的關閉連接只是把對象返回到連接池中,並非是真正的關閉
public synchronized void close() throws SQLException { if (isClosedInternal()) { // already closed return; } boolean isUnderlyingConectionClosed; try { isUnderlyingConectionClosed = getDelegateInternal().isClosed(); } catch (SQLException e) { try { _pool.invalidateObject(this); } catch(IllegalStateException ise) { // pool is closed, so close the connection passivate(); getInnermostDelegate().close(); } catch (Exception ie) { // DO NOTHING the original exception will be rethrown } throw new SQLException("Cannot close connection (isClosed check failed)", e); } /* Can‘t set close before this code block since the connection needs to * be open when validation runs. Can‘t set close after this code block * since by then the connection will have been returned to the pool and * may have been borrowed by another thread. Therefore, the close flag * is set in passivate(). */ if (isUnderlyingConectionClosed) { // Abnormal close: underlying connection closed unexpectedly, so we // must destroy this proxy try { _pool.invalidateObject(this); } catch(IllegalStateException e) { // pool is closed, so close the connection passivate(); getInnermostDelegate().close(); } catch (Exception e) { throw new SQLException("Cannot close connection (invalidating pooled object failed)", e); } } else { // Normal close: underlying connection is still open, so we // simply need to return this proxy to the pool try {
//將連接返回到連接池中 _pool.returnObject(this); } catch(IllegalStateException e) { // pool is closed, so close the connection passivate(); getInnermostDelegate().close(); } catch(SQLException e) { throw e; } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new SQLException("Cannot close connection (return to pool failed)", e); } } }
數據庫連接池DBCP源碼剖析