commons-dbcp 源码解读

DBCP是一个使用比较广泛的数据库连接池技术,基于apache的common-pool库。

主要暴露的类是 public class BasicDataSource implements DataSource

(这里插一段SPRING的内容,AbstractPlatformTransactionManager implements PlatformTransactionManager

的getTransaction方法,最终会调用到BasicDataSource的getConnection方法。)

BasicDataSource 的代码如下:

protected volatile GenericObjectPool connectionPool = null;  //这个就是连接池了。
protected volatile DataSource dataSource = null;   //通常这是一个PoolingDataSource
。。有很多配置项都会成为一个成员变量。

public Connection getConnection() throws SQLException {   //这是入口方法,最终在连接池里面borrowObject
        return createDataSource().getConnection();        //这里调用到了dataSource的getConnection、
                                                          //返回了一个PoolableConnection,代理了原始的connection
    }
protected synchronized DataSource createDataSource()
        throws SQLException {
        if (closed) {
            throw new SQLException("Data source is closed");
        }

        // Return the pool if we have already created it
        if (dataSource != null) {
            return (dataSource);
        }
        // create factory which returns raw physical connections  //创建connection的工厂
        ConnectionFactory driverConnectionFactory = createConnectionFactory();
        // create a pool for our connections       //创建连接池 connectionPool变量
        createConnectionPool();

        // Set up statement pool, if desired
        GenericKeyedObjectPoolFactory statementPoolFactory = null;
        if (isPoolPreparedStatements()) {
            statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
                        -1, // unlimited maxActive (per key)
                        GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
                        0, // maxWait
                        1, // maxIdle (per key)
                        maxOpenPreparedStatements);
        }

        // Set up the poolable connection factory
        createPoolableConnectionFactory(driverConnectionFactory, statementPoolFactory, abandonedConfig);

        // Create and return the pooling data source to manage the connections
        createDataSourceInstance();       //创建成员变量dataSource,通常这是一个PoolingDataSource
        
        try {
            for (int i = 0 ; i < initialSize ; i++) {
                connectionPool.addObject();            //这里初始化了连接池 initialSize 
            }
        } catch (Exception e) {
            throw new SQLNestedException("Error preloading the connection pool", e);
        }
        
        return dataSource;
    }

最后关闭连接的时候,调用了PoolableConnection的close. 将实际的连接归还到连接池。

PoolableConnection代码如下:

protected ObjectPool _pool = null;  //

 public synchronized void close() throws SQLException {
        if (_closed) {
            // already closed
            return;
        }

        boolean isUnderlyingConectionClosed;
        try {
            isUnderlyingConectionClosed = _conn.isClosed();
        } catch (SQLException e) {
            try {  //归还给连接池
                _pool.invalidateObject(this); // XXX should be guarded to happen at most once
            } 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 (SQLException) new SQLException("Cannot close connection (isClosed check failed)").initCause(e);
        }

        if (!isUnderlyingConectionClosed) {
            // Normal close: underlying connection is still open, so we
            // simply need to return this proxy to the pool
            try {
                _pool.returnObject(this); // XXX should be guarded to happen at most once
            } 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 (SQLException) new SQLException("Cannot close connection (return to pool failed)").initCause(e);
            }
        } else {
            // Abnormal close: underlying connection closed unexpectedly, so we
            // must destroy this proxy
            try {
                _pool.invalidateObject(this); // XXX should be guarded to happen at most once
            } catch(IllegalStateException e) {
                // pool is closed, so close the connection
                passivate();
                getInnermostDelegate().close();
            } catch (Exception ie) {
                // DO NOTHING, "Already closed" exception thrown below
            }
            throw new SQLException("Already closed.");
        }
    }

    

你可能感兴趣的:(commons-dbcp 源码解读)