本文次要钻研一下druid的return行为

close

com/alibaba/druid/pool/DruidPooledConnection.java

    @Override    public void close() throws SQLException {        if (this.disable) {            return;        }        DruidConnectionHolder holder = this.holder;        if (holder == null) {            if (dupCloseLogEnable) {                LOG.error("dup close");            }            return;        }        DruidAbstractDataSource dataSource = holder.getDataSource();        boolean isSameThread = this.getOwnerThread() == Thread.currentThread();        if (!isSameThread) {            dataSource.setAsyncCloseConnectionEnable(true);        }        if (dataSource.isAsyncCloseConnectionEnable()) {            syncClose();            return;        }        if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {            return;        }        try {            for (ConnectionEventListener listener : holder.getConnectionEventListeners()) {                listener.connectionClosed(new ConnectionEvent(this));            }            List<Filter> filters = dataSource.getProxyFilters();            if (filters.size() > 0) {                FilterChainImpl filterChain = new FilterChainImpl(dataSource);                filterChain.dataSource_recycle(this);            } else {                recycle();            }        } finally {            CLOSING_UPDATER.set(this, 0);        }        this.disable = true;    }
close办法先从holder获取以后的dataSource,而后判断ownerThread,若不是同一个线程则设置asyncCloseConnectionEnable为true,若asyncCloseConnectionEnable为true则执行syncClose(这里语义貌似相同),否则执行recycle办法

syncClose

com/alibaba/druid/pool/DruidPooledConnection.java

    public void syncClose() throws SQLException {        lock.lock();        try {            if (this.disable || CLOSING_UPDATER.get(this) != 0) {                return;            }            DruidConnectionHolder holder = this.holder;            if (holder == null) {                if (dupCloseLogEnable) {                    LOG.error("dup close");                }                return;            }            if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {                return;            }            for (ConnectionEventListener listener : holder.getConnectionEventListeners()) {                listener.connectionClosed(new ConnectionEvent(this));            }            DruidAbstractDataSource dataSource = holder.getDataSource();            List<Filter> filters = dataSource.getProxyFilters();            if (filters.size() > 0) {                FilterChainImpl filterChain = new FilterChainImpl(dataSource);                filterChain.dataSource_recycle(this);            } else {                recycle();            }            this.disable = true;        } finally {            CLOSING_UPDATER.set(this, 0);            lock.unlock();        }    }
syncClose办法次要是加锁执行recycle

recycle

    public void recycle() throws SQLException {        if (this.disable) {            return;        }        DruidConnectionHolder holder = this.holder;        if (holder == null) {            if (dupCloseLogEnable) {                LOG.error("dup close");            }            return;        }        if (!this.abandoned) {            DruidAbstractDataSource dataSource = holder.getDataSource();            dataSource.recycle(this);        }        this.holder = null;        conn = null;        transactionInfo = null;        closed = true;    }
recycle办法次要是执行dataSource.recycle(this)

DruidDataSource.recycle

com/alibaba/druid/pool/DruidDataSource.java

    protected void recycle(DruidPooledConnection pooledConnection) throws SQLException {        final DruidConnectionHolder holder = pooledConnection.holder;        if (holder == null) {            LOG.warn("connectionHolder is null");            return;        }        if (logDifferentThread //                && (!isAsyncCloseConnectionEnable()) //                && pooledConnection.ownerThread != Thread.currentThread()//        ) {            LOG.warn("get/close not same thread");        }        final Connection physicalConnection = holder.conn;        if (pooledConnection.traceEnable) {            Object oldInfo = null;            activeConnectionLock.lock();            try {                if (pooledConnection.traceEnable) {                    oldInfo = activeConnections.remove(pooledConnection);                    pooledConnection.traceEnable = false;                }            } finally {                activeConnectionLock.unlock();            }            if (oldInfo == null) {                if (LOG.isWarnEnabled()) {                    LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size());                }            }        }        final boolean isAutoCommit = holder.underlyingAutoCommit;        final boolean isReadOnly = holder.underlyingReadOnly;        final boolean testOnReturn = this.testOnReturn;        try {            // check need to rollback?            if ((!isAutoCommit) && (!isReadOnly)) {                pooledConnection.rollback();            }            // reset holder, restore default settings, clear warnings            boolean isSameThread = pooledConnection.ownerThread == Thread.currentThread();            if (!isSameThread) {                final ReentrantLock lock = pooledConnection.lock;                lock.lock();                try {                    holder.reset();                } finally {                    lock.unlock();                }            } else {                holder.reset();            }            if (holder.discard) {                return;            }            if (phyMaxUseCount > 0 && holder.useCount >= phyMaxUseCount) {                discardConnection(holder);                return;            }            if (physicalConnection.isClosed()) {                lock.lock();                try {                    if (holder.active) {                        activeCount--;                        holder.active = false;                    }                    closeCount++;                } finally {                    lock.unlock();                }                return;            }            if (testOnReturn) {                boolean validate = testConnectionInternal(holder, physicalConnection);                if (!validate) {                    JdbcUtils.close(physicalConnection);                    destroyCountUpdater.incrementAndGet(this);                    lock.lock();                    try {                        if (holder.active) {                            activeCount--;                            holder.active = false;                        }                        closeCount++;                    } finally {                        lock.unlock();                    }                    return;                }            }            if (holder.initSchema != null) {                holder.conn.setSchema(holder.initSchema);                holder.initSchema = null;            }            if (!enable) {                discardConnection(holder);                return;            }            boolean result;            final long currentTimeMillis = System.currentTimeMillis();            if (phyTimeoutMillis > 0) {                long phyConnectTimeMillis = currentTimeMillis - holder.connectTimeMillis;                if (phyConnectTimeMillis > phyTimeoutMillis) {                    discardConnection(holder);                    return;                }            }            lock.lock();            try {                if (holder.active) {                    activeCount--;                    holder.active = false;                }                closeCount++;                result = putLast(holder, currentTimeMillis);                recycleCount++;            } finally {                lock.unlock();            }            if (!result) {                JdbcUtils.close(holder.conn);                LOG.info("connection recyle failed.");            }        } catch (Throwable e) {            holder.clearStatementCache();            if (!holder.discard) {                discardConnection(holder);                holder.discard = true;            }            LOG.error("recyle error", e);            recycleErrorCountUpdater.incrementAndGet(this);        }    }    boolean putLast(DruidConnectionHolder e, long lastActiveTimeMillis) {        if (poolingCount >= maxActive || e.discard || this.closed) {            return false;        }        e.lastActiveTimeMillis = lastActiveTimeMillis;        connections[poolingCount] = e;        incrementPoolingCount();        if (poolingCount > poolingPeak) {            poolingPeak = poolingCount;            poolingPeakTime = lastActiveTimeMillis;        }        notEmpty.signal();        notEmptySignalCount++;        return true;    }
recycle办法先执行DruidConnectionHolder的reset办法,之后针对大于等于phyMaxUseCount的场景执行discardConnection;针对testOnReturn为true,则执行testConnectionInternal校验,校验失败则敞开连贯;最初加锁执行putLast把连贯放回连接池,若偿还失败则敞开连贯。

小结

close办法先从holder获取以后的dataSource,而后判断ownerThread,若不是同一个线程则设置asyncCloseConnectionEnable为true,若asyncCloseConnectionEnable为true则执行syncClose(这里语义貌似相同),否则执行recycle办法。