commons-dbcp 源码解读

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

配置:

http://my.oschina.net/robinsonlu/blog/77759

如何使用:

http://my.oschina.net/donghongyu/blog/190494

主要机制如下:

  1. 拥有若干配置,initialSize初始化的连接池大小,maxActive最大,testWhileIdle,validationQuery等等参数保持了连接的有效性。

  2. 当连接池满时,有多种策略。WHEN_EXHAUSTED_BLOCK 是默认的,还可以有使用新的连接,或则抛出异常。

  3. 每次borrow连接时候,从池种获取一个连接,并test这个连接;return同样需要测试这个连接。 连接池构造函数的最后一句,开启了一个timer,周期性调用evict(), 检查和测试池中的连接。


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

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

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

BasicDataSource 的代码如下:

protected volatile GenericObjectPool connectionPool = null;  //这个就是连接池了。
protected volatile DataSource dataSource = null;   //通常这是一个PoolingDataSource ,这个对象也hold一个connectionPool对象
。。每个连接池的配置项都会成为一个成员变量。

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. 将实际的连接归还到连接池。

2. PoolableConnection代码如下:

PoolableConnection继承自DelegatingConnection类。

public class PoolableConnection extends DelegatingConnection {
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.");
        }
    }

   3. PoolableConnectionFactory 是创建连接的工厂类。

makeObject方法创建一个Connection实例,并使用PoolableConnection进行了代理。

还有以下方法:passivateObject,activateObject 方法 只是简单的设置了DelegatingConnection的isClosed的值。validateConnection 执行了一条测试的SQL。

public Object makeObject() throws Exception {
        Connection conn = _connFactory.createConnection();
        if (conn == null) {
            throw new IllegalStateException("Connection factory returned null from createConnection");
        }
        initializeConnection(conn);
        if(null != _stmtPoolFactory) {
            KeyedObjectPool stmtpool = _stmtPoolFactory.createPool();
            conn = new PoolingConnection(conn,stmtpool);
            stmtpool.setFactory((PoolingConnection)conn);
        }
        return new PoolableConnection(conn,_pool,_config);
    }

4 . GenericObjectPool 类是连接池的hold的对象。这个类是连接池实现的核心类,但是方法都特别长,描述一下把。

    它拥有一个private子类型Latch,

private CursorableLinkedList _pool = null;  //这个地方保留了连接池的链表

/** Eviction cursor - keeps track of idle object evictor position */
private CursorableLinkedList.Cursor _evictionCursor = null;  链表当前的位置
private LinkedList _allocationQueue = new LinkedList();      等待分配的queue
 
private static final class Latch {
private ObjectTimestampPair _pair;} //这个_pair 会hold一个connection,供调用borrowObject方法返回。

下面描述GenericObjectPool 的主要方法的行为。
//下面这个方法就是从池中借出一个connection。 1。 首先 实例化一个Latch加入到_allocationQueue中,然后调用allocate()方法,取从_pool中分配一个connection,到_allocationQueue。2。判断自己的Latch有没有拿到连接。如果没有拿到按照配置的策略取等待,失败或则新建连接。3 得到连接之后,激活并测试连接。第三步可能跑出异常.
public Object borrowObject(Object key) throws Exception {

这个方法很关键,分配Connection到_allocationQueue的Latch对象中,或则设置为Latch自己去新建
private synchronized void allocate() {

当归还一个对象时调用这个方法,这个方法的主要逻辑在addObjectToPool方法中。1. validateObject这个对象,如果成功,则钝化这个对象。 2. 如果validate成功,就把这个对象加入到 _pool 中。3 失败,则destroyObject。
public void returnObject(Object obj) throws Exception { 
            addObjectToPool(obj, true);

evict这个方法,在连接池初始化的时候,会新建一个timer。 这个方法很关键,如果不进行evict,连接池就无法保持和数据库的长连接。 
这个方法 遍历了_pool中的对象,调用activateObject,validateObject,passivateObject,验证当前的Object的可用性,如果不可用,就移除。
//startEvictor(_timeBetweenEvictionRunsMillis);
public void evict() throws Exception {


转载于:https://my.oschina.net/u/2504171/blog/546346

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值