DBCP2获取连接

来源:互联网 发布:网络彩票推广员 编辑:程序博客网 时间:2024/06/14 18:47

DBCP2获取连接

如果是初次获取连接会进行一系列操作,如下图所示;
这里写图片描述
包括:

  • 在静态初始化BasicDataSource时加载相关类,避免在使用getConnection获取连接时有些类没被加载导致AccessControlException
  • createConnectonFactory创建Connection工厂,用于获取原生物理连接。这边有个有趣的操作是在当前类加载器获取不到驱动类时,尝试使用当前线程上线文类加载器去获取
  • createPoolableConnectionFactory,创建池化连接池,用于封装和管理原生Connection,包括:
    • activateObject,设置连接是否默认提交、事务隔离级别、是否只读、语句查询超时时间,这些都可以配置
    • validateConnection,验证连接是否可用,有两个方式:1.没有配置validationQuery属性时,采用数据库驱动提供的验证方式;2.有配置的话,通过配置发送查询语句。暂时不清楚两种方式优劣,感觉直接采用官方提供的比较靠谱
    • passivateObject,用于归还或销毁连接时,如果设置rollbackOnReturn为true(默认为true),且在activateObject中设置连接为不自动提交和不是只读,则在归还连接时进行回滚。如果设置enableAutoCommitOnReturn为true(默认为true)如果连接不是自动提交,则设置为自动提交,用于确保空闲连接可自动提交。
      上面三个方法都会先验证池化Connection的生命时长(配置参数maxConnLifetimeMillis控制),如果超过则抛出异常
  • createConnectionPool,创建连接池,采用生产者消费者模式管理池化连接,处理并发问题
    获取连接的调用顺序BasicDataSource.getConnection -> PoolingDataSource.getConnection -> GenericObjectPool.borrowObject ->PoolableConnectionFactory.makeFacotory

下面直接上代码:
在GenericObjectPool类

public T borrowObject(long borrowMaxWaitMillis) throws Exception {        assertOpen();        AbandonedConfig ac = this.abandonedConfig;        if (ac != null && ac.getRemoveAbandonedOnBorrow() &&                (getNumIdle() < 2) &&                (getNumActive() > getMaxTotal() - 3) ) {            removeAbandoned(ac);        }        PooledObject<T> p = null;        // Get local copy of current config so it is consistent for entire        // method execution        boolean blockWhenExhausted = getBlockWhenExhausted();        boolean create;        long waitTime = System.currentTimeMillis();        while (p == null) {            create = false;            if (blockWhenExhausted) {                p = idleObjects.pollFirst();                if (p == null) {                    p = create();                    if (p != null) {                        create = true;                    }                }                if (p == null) {                    if (borrowMaxWaitMillis < 0) {                        p = idleObjects.takeFirst();                    } else {                        p = idleObjects.pollFirst(borrowMaxWaitMillis,                                TimeUnit.MILLISECONDS);                    }                }                if (p == null) {                    throw new NoSuchElementException(                            "Timeout waiting for idle object");                }                if (!p.allocate()) {                    p = null;                }            } else {                p = idleObjects.pollFirst();                if (p == null) {                    p = create();                    if (p != null) {                        create = true;                    }                }                if (p == null) {                    throw new NoSuchElementException("Pool exhausted");                }                if (!p.allocate()) {                    p = null;                }            }            if (p != null) {                try {                    factory.activateObject(p);                } catch (Exception e) {                    try {                        destroy(p);                    } catch (Exception e1) {                        // Ignore - activation failure is more important                    }                    p = null;                    if (create) {                        NoSuchElementException nsee = new NoSuchElementException(                                "Unable to activate object");                        nsee.initCause(e);                        throw nsee;                    }                }                if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {                    boolean validate = false;                    Throwable validationThrowable = null;                    try {                        validate = factory.validateObject(p);                    } catch (Throwable t) {                        PoolUtils.checkRethrow(t);                        validationThrowable = t;                    }                    if (!validate) {                        try {                            destroy(p);                            destroyedByBorrowValidationCount.incrementAndGet();                        } catch (Exception e) {                            // Ignore - validation failure is more important                        }                        p = null;                        if (create) {                            NoSuchElementException nsee = new NoSuchElementException(                                    "Unable to validate object");                            nsee.initCause(validationThrowable);                            throw nsee;                        }                    }                }            }        }        updateStatsBorrow(p, System.currentTimeMillis() - waitTime);        return p.getObject();    }

获取连接分两种情况:
1. 设置超时等待的情况,先尝试从空闲队列获取连接(不等待直接返回),不成功采用超时等待方式从空闲队列获取连接,如果没有获取连接则抛出异常。如果获取成功则激活连接、根据配置(testOnBorrow或testOnCreate)验证连接
2. 没设置超时等待情况,尝试从空闲队列获取连接(不等待直接返回)

注意,在获取连接时,如果符合下面条件将会回收弃用连接:

if (ac != null && ac.getRemoveAbandonedOnBorrow() &&                (getNumIdle() < 2) &&                (getNumActive() > getMaxTotal() - 3) ) {            removeAbandoned(ac);        }
原创粉丝点击