druid return行为方法源码示例解析

 更新时间:2023年09月26日 09:21:17   作者:codecraft  
这篇文章主要为大家介绍了druid return行为源码示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下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方法。

以上就是druid return行为源码示例解析的详细内容,更多关于druid return行为的资料请关注脚本之家其它相关文章!

相关文章

  • Mybatis generator自动生成代码插件实例解析

    Mybatis generator自动生成代码插件实例解析

    这篇文章主要介绍了Mybatis generator自动生成代码插件实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • java 使用memcached以及spring 配置memcached完整实例代码

    java 使用memcached以及spring 配置memcached完整实例代码

    本篇文章主要介绍了java 使用memcached以及spring 配置memcached完整实例代码,具有一定的参考价值,有兴趣的可以了解一下
    2017-07-07
  • Java获取时间差(天数差,小时差,分钟差)代码示例

    Java获取时间差(天数差,小时差,分钟差)代码示例

    这篇文章主要介绍了Java获取时间差(天数差,小时差,分钟差)代码示例,使用SimpleDateFormat来实现的相关代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • java8、jdk8日期转化成字符串详解

    java8、jdk8日期转化成字符串详解

    在本篇文章中小编给大家整理了关于java8、jdk8日期转化成字符串的相关知识点和代码,需要的朋友们学习下。
    2019-04-04
  • Java面试之如何实现10亿数据判重

    Java面试之如何实现10亿数据判重

    当数据量比较大时,使用常规的方式来判重就不行了,所以这篇文章小编主要来和大家介绍一下Java实现10亿数据判重的相关方法,希望对大家有所帮助
    2024-02-02
  • Java 如何通过Magic 魔数获取文件类型

    Java 如何通过Magic 魔数获取文件类型

    魔数有很多种定义,这里我们讨论的主要是在编程领域的定义,文件的起始几个字节的内容是固定的,本文给大家介绍Java Magic 魔数获取文件类型的相关知识,感兴趣的朋友一起看看吧
    2023-11-11
  • 详解Spring-Boot中如何使用多线程处理任务

    详解Spring-Boot中如何使用多线程处理任务

    本篇文章主要介绍了详解Spring-Boot中如何使用多线程处理任务,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • minio的下载和springboot整合minio使用方法

    minio的下载和springboot整合minio使用方法

    本文介绍了如何通过Docker拉取MinIO镜像,并创建MinIO容器的过程,首先,需要在本地创建/data和/conf两个目录用于挂载MinIO的数据和配置文件,接下来,通过docker run命令启动容器,设置MinIO的访问端口、用户名、密码等信息,感兴趣的朋友一起看看吧
    2024-09-09
  • Java使用easypoi快速导入导出的实现

    Java使用easypoi快速导入导出的实现

    这篇文章主要介绍了实现Java使用easypoi快速导入导出的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • Java中token的存储和获取实例代码

    Java中token的存储和获取实例代码

    关于java获取微信Token验证的问题相信很多人都遇见过,尤其是对刚接触微信开发的人来说确实有点棘手,下面这篇文章主要给大家介绍了关于Java中token存储和获取的相关资料,需要的朋友可以参考下
    2022-08-08

最新评论