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);
        }

转载于:https://my.oschina.net/u/252559/blog/1579909

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值