数据库连接池DBCP框架的研究以及源代码分析三:打开AbandonedObjectPool连接池

前面,我们已经找到了真正的DataSource,这个类就是PoolingDataSource 

同时,也找到了对象状态维护工厂PoolableConnectionFactory目前不用急于往下看代码,如果再继续看,就容易晕,先从整体上思考一下,既然DBCP可以处理我们没有关闭的连接,那么,它的一定有自己的对象池,而且必须继承自GenericObjectPool,我们根据GenericObjectPool进行搜索,就找到了AbandonedObjectPool这个核心的连接池。

   

AbandonedObjectPool有一个配置文件属性,也就是AbandonedConfig类的对象,我们先看看这个类包括了哪些属性(这些属性非常重要,我们今后可能不会去写DBCP,但要使用DBCP就必须配置这些属性):

 

public class AbandonedConfig {

 

 //是否移除超时不使用的连接

    private boolean removeAbandoned = false;

   //超时时间

private int removeAbandonedTimeout = 300;

 //是否记录日志 

    private boolean logAbandoned = false;

  //日志对象 

    private PrintWriter logWriter = newPrintWriter(System.out);

//省略GET\SET方法一批

}

再来看看AbandonedObjectPool类:

public class AbandonedObjectPool extends GenericObjectPool {

 

    //DBCP配置对象

    private final AbandonedConfig config;

  //使用中的连接

    private final List trace = new ArrayList();

    public AbandonedObjectPool(PoolableObjectFactoryfactory,

                               AbandonedConfig config) {

        super(factory);

        this.config = config;

    }

//从连接池中取出对象

    public Object borrowObject() throws Exception {

        if (config != null

                && config.getRemoveAbandoned()

                && (getNumIdle() <2)//空闲连接小于2

                && (getNumActive() >getMaxActive() - 3) ) {

//借出的连接大于最大连接-3

//即借出的+空闲的大于等于最大连接数

            removeAbandoned();//移除连接,在这个方法里面判断是否超时

        }

        Object obj = super.borrowObject();

        if (obj instanceof AbandonedTrace) {

            ((AbandonedTrace)obj).setStackTrace();

        }

        if (obj != null && config != null && config.getRemoveAbandoned()) {

            synchronized (trace) {

                trace.add(obj);

            }

        }

        return obj;

    }

  /**

     * 移除没有使用的超时连接

     *

     */

    private void removeAbandoned() {

        // Generate a list of abandoned connections to remove

        long now = System.currentTimeMillis();

        long timeout = now - (config.getRemoveAbandonedTimeout() * 1000);//当前时间-超时时间*1000),得到过去的某个时间点,在此时间点之前就是超时

        ArrayList remove = new ArrayList();//用于保存需要移除的连接

        synchronized (trace) {

            Iterator it = trace.iterator();

            while (it.hasNext()) {

                AbandonedTrace pc =(AbandonedTrace) it.next();//注意, AbandonedTrace很重要,是继承Connection接口,是所有代理Connection的基类

                if (pc.getLastUsed() > timeout) {//不超时

                    continue;

                }

                if (pc.getLastUsed() > 0) {//超时的,而且最近有使用过

                    remove.add(pc);

                }

            }

        }

        Iterator it = remove.iterator();

        while (it.hasNext()) {

            AbandonedTrace pc =(AbandonedTrace) it.next();

            if (config.getLogAbandoned()) {

                pc.printStackTrace();

            }            

            try {

                invalidateObject(pc);//将连接设置为无效

            } catch (Exception e) {

                e.printStackTrace();

            }

           

        }

    }

 

    //归还对象,没有什么可说

    public void returnObject(Object obj) throws Exception {

        if (config != null && config.getRemoveAbandoned()) {

            synchronized (trace) {

                boolean foundObject = trace.remove(obj);

                if (!foundObject) {

                    return; // This connection has already been invalidated.  Stop now.

                }

            }

        }

        super.returnObject(obj);

    }

 

  

    public void invalidateObject(Object obj) throws Exception {

        if (config != null && config.getRemoveAbandoned()) {

            synchronized (trace) {

                boolean foundObject = trace.remove(obj);

                if (!foundObject) {

                    return; // This connection has already been invalidated.  Stop now.

                }

            }

        }

        super.invalidateObject(obj); //看到没有,实际上是调用父类来将其设置为无效的      

    }

 

}

 

我们知道,我们自己使用对象池时,需要传递一个对象状态维护工厂,这个工厂继承PoolableObjectFactory接口,在该工厂中,实现对连接的真正维护,通过前面的学习,我们找到了该对象状态工厂类就是: PoolableConnectionFactory,再来看看这个类的代码:

public class PoolableConnectionFactoryimplements PoolableObjectFactory {

   //省略构造函数一大批

  protected volatile ConnectionFactory _connFactory = null;

    protected volatile String _validationQuery = null;//验证的SQL

    protected volatile int _validationQueryTimeout = -1;//验证的超时时间

    protected Collection _connectionInitSqls = null;//连接成功的初始化语句

    protected volatile ObjectPool _pool = null;

    protected volatile KeyedObjectPoolFactory _stmtPoolFactory = null;

    protected Boolean _defaultReadOnly = null;//默认是否只读

    protected boolean _defaultAutoCommit = true;//是否自动提交(true即不启动事务)

    protected int _defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;//默认数据库隔离级别

    protected String _defaultCatalog;//默认数据库名称

    protected AbandonedConfig _config = null;

    static final int UNKNOWN_TRANSACTIONISOLATION = -1;

 

//这里省略对属性进行GetSet的方法一批

  

//创建对象

    public Object makeObject() throws Exception {

        Connection conn = _connFactory.createConnection();

        if (conn == null) {

            throw new IllegalStateException("Connection factory returned null from createConnection");

        }

        initializeConnection(conn);//初始化连接,即生成连接并尝试去执行SQL

        if(null != _stmtPoolFactory) {

            KeyedObjectPool stmtpool = _stmtPoolFactory.createPool();

            conn = newPoolingConnection(conn,stmtpool);//这个连接是对真正Connection的进一步封装,注意,这个类是后面的重点。

           stmtpool.setFactory((PoolingConnection)conn);

        }

        return new PoolableConnection(conn,_pool,_config);

    }

//初始化连接

    protected void initializeConnection(Connection conn) throws SQLException {

        Collection sqls = _connectionInitSqls;

        if(conn.isClosed()) {

            throw new SQLException("initializeConnection:connection closed");

        }

        if(null != sqls) {

            Statement stmt = null;

            try {

                stmt = conn.createStatement();

                for (Iterator iterator = sqls.iterator();iterator.hasNext();)

                {

                    Object o = iterator.next();

                    if (o == null) {

                        throw new NullPointerException("null connectionInitSqls element");

                    }

                    // o might not be a String instance

                    String sql = o.toString();

                    stmt.execute(sql);

                }

            } finally {

                if (stmt != null) {

                    try {

                        stmt.close();

                    } catch(Exception t) {

                        // ignored

                    }

                }

            }

        }

    }

//销毁连接

    public void destroyObject(Object obj) throws Exception {

        if(obj instanceof PoolableConnection) {

           ((PoolableConnection)obj).reallyClose();//看来,有真正的关闭也有假的关闭啊,假的关闭多半就是close方法

        }

    }

//验证对象

    public boolean validateObject(Object obj) {

        if(obj instanceof Connection) {

            try {

                validateConnection((Connection)obj);

                return true;

            } catch(Exception e) {

                return false;

            }

        } else {

            return false;

        }

    }

//验证连接,实际就是执行我们传递进来的SQL

    public void validateConnection(Connection conn) throws SQLException {

        String query = _validationQuery;

        if(conn.isClosed()) {

            throw new SQLException("validateConnection:connection closed");

        }

        if(null != query) {

            Statement stmt = null;

            ResultSet rset = null;

            try {

                stmt = conn.createStatement();

                if (_validationQueryTimeout > 0) {

                    stmt.setQueryTimeout(_validationQueryTimeout);

                }

                rset =stmt.executeQuery(query);

                if(!rset.next()) {

                    throw new SQLException("validationQuerydidn't return a row");

                }

            } finally {

                if (rset != null) {

                    try {

                        rset.close();

                    } catch(Exception t) {

                        // ignored

                    }

                }

                if (stmt != null) {

                    try {

                        stmt.close();

                    } catch(Exception t) {

                        // ignored

                    }

                }

            }

        }

    }

//归还对象执行动作

    public void passivateObject(Object obj) throws Exception {

        if(obj instanceof Connection){

            Connection conn = (Connection)obj;

            if(!conn.getAutoCommit() &&!conn.isReadOnly()) {

                conn.rollback();

            }

            conn.clearWarnings();

            if(!conn.getAutoCommit()) {

                conn.setAutoCommit(true);

            }

        }

        if(obj instanceof DelegatingConnection) {

           ((DelegatingConnection)obj).passivate();

        }

    }

    //激活对象

    public void activateObject(Object obj) throws Exception {

        if(obj instanceof DelegatingConnection) {

           ((DelegatingConnection)obj).activate();

        }

        if(obj instanceof Connection) {

            Connection conn = (Connection)obj;

            if (conn.getAutoCommit() != _defaultAutoCommit) {

                conn.setAutoCommit(_defaultAutoCommit);

            }

            if ((_defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION)

                    &&(conn.getTransactionIsolation() !=

                    _defaultTransactionIsolation)) {

                conn.setTransactionIsolation(_defaultTransactionIsolation);

            }

            if ((_defaultReadOnly != null) &&

                    (conn.isReadOnly() != _defaultReadOnly.booleanValue())){

                conn.setReadOnly(_defaultReadOnly.booleanValue());

            }

            if ((_defaultCatalog != null) &&

                    (!_defaultCatalog.equals(conn.getCatalog()))) {

                conn.setCatalog(_defaultCatalog);

            }

        }

    }

 

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值