最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

druid?handleException執(zhí)行流程源碼解析

 更新時(shí)間:2023年09月27日 14:03:09   作者:codecraft  
這篇文章主要為大家介紹了druid?handleException執(zhí)行流程源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下druid的handleException

prepareStatement

com/alibaba/druid/pool/DruidPooledConnection.java

public PreparedStatement prepareStatement(String sql) throws SQLException {
        checkState();
        PreparedStatementHolder stmtHolder = null;
        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M1);
        boolean poolPreparedStatements = holder.isPoolPreparedStatements();
        if (poolPreparedStatements) {
            stmtHolder = holder.getStatementPool().get(key);
        }
        if (stmtHolder == null) {
            try {
                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql));
                holder.getDataSource().incrementPreparedStatementCount();
            } catch (SQLException ex) {
                handleException(ex, sql);
            }
        }
        initStatement(stmtHolder);
        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
        holder.addTrace(rtnVal);
        return rtnVal;
    }
DruidPooledConnection的prepareStatement會(huì)catch住SQLException然后執(zhí)行handleException

executeQuery

com/alibaba/druid/pool/DruidPooledPreparedStatement.java

public ResultSet executeQuery() throws SQLException {
        checkOpen();
        incrementExecuteQueryCount();
        transactionRecord(sql);
        oracleSetRowPrefetch();
        conn.beforeExecute();
        try {
            ResultSet rs = stmt.executeQuery();
            if (rs == null) {
                return null;
            }
            DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);
            addResultSetTrace(poolableResultSet);
            return poolableResultSet;
        } catch (Throwable t) {
            errorCheck(t);
            throw checkException(t);
        } finally {
            conn.afterExecute();
        }
    }
executeQuery在catch到Throwable時(shí)會(huì)執(zhí)行throw checkException(t)

checkException

com/alibaba/druid/pool/DruidPooledStatement.java

protected SQLException checkException(Throwable error) throws SQLException {
        String sql = null;
        if (this instanceof DruidPooledPreparedStatement) {
            sql = ((DruidPooledPreparedStatement) this).getSql();
        }
        handleSocketTimeout(error);
        exceptionCount++;
        return conn.handleException(error, sql);
    }
checkException這里會(huì)執(zhí)行conn.handleException(error, sql)

handleException

public SQLException handleException(Throwable t, String sql) throws SQLException {
        final DruidConnectionHolder holder = this.holder;
        //
        if (holder != null) {
            DruidAbstractDataSource dataSource = holder.getDataSource();
            dataSource.handleConnectionException(this, t, sql);
        }
        if (t instanceof SQLException) {
            throw (SQLException) t;
        }
        throw new SQLException("Error", t);
    }
handleException這里是委托給了dataSource.handleConnectionException(this, t, sql);

handleConnectionException

com/alibaba/druid/pool/DruidDataSource.java

public void handleConnectionException(DruidPooledConnection pooledConnection,
                                          Throwable t,
                                          String sql) throws SQLException {
        final DruidConnectionHolder holder = pooledConnection.getConnectionHolder();
        if (holder == null) {
            return;
        }
        errorCountUpdater.incrementAndGet(this);
        lastError = t;
        lastErrorTimeMillis = System.currentTimeMillis();
        if (t instanceof SQLException) {
            SQLException sqlEx = (SQLException) t;
            // broadcastConnectionError
            ConnectionEvent event = new ConnectionEvent(pooledConnection, sqlEx);
            for (ConnectionEventListener eventListener : holder.getConnectionEventListeners()) {
                eventListener.connectionErrorOccurred(event);
            }
            // exceptionSorter.isExceptionFatal
            if (exceptionSorter != null && exceptionSorter.isExceptionFatal(sqlEx)) {
                handleFatalError(pooledConnection, sqlEx, sql);
            }
            throw sqlEx;
        } else {
            throw new SQLException("Error", t);
        }
    }
handleConnectionException方法在exceptionSorter.isExceptionFatal(sqlEx)為true時(shí)會(huì)執(zhí)行handleFatalError

isExceptionFatal

com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java

public class MySqlExceptionSorter implements ExceptionSorter {
    @Override
    public boolean isExceptionFatal(SQLException e) {
        if (e instanceof SQLRecoverableException) {
            return true;
        }
        final String sqlState = e.getSQLState();
        final int errorCode = e.getErrorCode();
        if (sqlState != null && sqlState.startsWith("08")) {
            return true;
        }
        switch (errorCode) {
            // Communications Errors
            case 1040: // ER_CON_COUNT_ERROR
            case 1042: // ER_BAD_HOST_ERROR
            case 1043: // ER_HANDSHAKE_ERROR
            case 1047: // ER_UNKNOWN_COM_ERROR
            case 1081: // ER_IPSOCK_ERROR
            case 1129: // ER_HOST_IS_BLOCKED
            case 1130: // ER_HOST_NOT_PRIVILEGED
                // Authentication Errors
            case 1045: // ER_ACCESS_DENIED_ERROR
                // Resource errors
            case 1004: // ER_CANT_CREATE_FILE
            case 1005: // ER_CANT_CREATE_TABLE
            case 1015: // ER_CANT_LOCK
            case 1021: // ER_DISK_FULL
            case 1041: // ER_OUT_OF_RESOURCES
                // Out-of-memory errors
            case 1037: // ER_OUTOFMEMORY
            case 1038: // ER_OUT_OF_SORTMEMORY
                // Access denied
            case 1142: // ER_TABLEACCESS_DENIED_ERROR
            case 1227: // ER_SPECIFIC_ACCESS_DENIED_ERROR
            case 1023: // ER_ERROR_ON_CLOSE
            case 1290: // ER_OPTION_PREVENTS_STATEMENT
                return true;
            default:
                break;
        }
        // for oceanbase
        if (errorCode >= -9000 && errorCode <= -8000) {
            return true;
        }
        String className = e.getClass().getName();
        if (className.endsWith(".CommunicationsException")) {
            return true;
        }
        String message = e.getMessage();
        if (message != null && message.length() > 0) {
            if (message.startsWith("Streaming result set com.mysql.jdbc.RowDataDynamic")
                    && message.endsWith("is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.")) {
                return true;
            }
            final String errorText = message.toUpperCase();
            if ((errorCode == 0 && (errorText.contains("COMMUNICATIONS LINK FAILURE")) //
                    || errorText.contains("COULD NOT CREATE CONNECTION")) //
                    || errorText.contains("NO DATASOURCE") //
                    || errorText.contains("NO ALIVE DATASOURCE")) {
                return true;
            }
        }
        Throwable cause = e.getCause();
        for (int i = 0; i < 5 && cause != null; ++i) {
            if (cause instanceof SocketTimeoutException) {
                return true;
            }
            className = cause.getClass().getName();
            if (className.endsWith(".CommunicationsException")) {
                return true;
            }
            cause = cause.getCause();
        }
        return false;
    }
    @Override
    public void configFromProperties(Properties properties) {
    }
}
MySqlExceptionSorter針對(duì)指定錯(cuò)誤碼來(lái)判斷是否fatal

handleFatalError

com/alibaba/druid/pool/DruidDataSource.java

protected final void handleFatalError(DruidPooledConnection conn,
                                          SQLException error,
                                          String sql) throws SQLException {
        final DruidConnectionHolder holder = conn.holder;
        if (conn.isTraceEnable()) {
            activeConnectionLock.lock();
            try {
                if (conn.isTraceEnable()) {
                    activeConnections.remove(conn);
                    conn.setTraceEnable(false);
                }
            } finally {
                activeConnectionLock.unlock();
            }
        }
        long lastErrorTimeMillis = this.lastErrorTimeMillis;
        if (lastErrorTimeMillis == 0) {
            lastErrorTimeMillis = System.currentTimeMillis();
        }
        if (sql != null && sql.length() > 1024) {
            sql = sql.substring(0, 1024);
        }
        boolean requireDiscard = false;
        final ReentrantLock lock = conn.lock;
        lock.lock();
        try {
            if ((!conn.isClosed()) || !conn.isDisable()) {
                conn.disable(error);
                requireDiscard = true;
            }
            lastFatalErrorTimeMillis = lastErrorTimeMillis;
            fatalErrorCount++;
            if (fatalErrorCount - fatalErrorCountLastShrink > onFatalErrorMaxActive) {
                onFatalError = true;
            }
            lastFatalError = error;
            lastFatalErrorSql = sql;
        } finally {
            lock.unlock();
        }
        if (onFatalError && holder != null && holder.getDataSource() != null) {
            ReentrantLock dataSourceLock = holder.getDataSource().lock;
            dataSourceLock.lock();
            try {
                emptySignal();
            } finally {
                dataSourceLock.unlock();
            }
        }
        if (requireDiscard) {
            if (holder.statementTrace != null) {
                holder.lock.lock();
                try {
                    for (Statement stmt : holder.statementTrace) {
                        JdbcUtils.close(stmt);
                    }
                } finally {
                    holder.lock.unlock();
                }
            }
            this.discardConnection(holder);
        }
        // holder.
        LOG.error("{conn-" + holder.getConnectionId() + "} discard", error);
    }
handleFatalError方法這里會(huì)執(zhí)行conn.disable(error),然后標(biāo)記requireDiscard為true,最后執(zhí)行discardConnection

discardConnection

com/alibaba/druid/pool/DruidDataSource.java

public void discardConnection(DruidConnectionHolder holder) {
        if (holder == null) {
            return;
        }
        Connection conn = holder.getConnection();
        if (conn != null) {
            JdbcUtils.close(conn);
        }
        lock.lock();
        try {
            if (holder.discard) {
                return;
            }
            if (holder.active) {
                activeCount--;
                holder.active = false;
            }
            discardCount++;
            holder.discard = true;
            if (activeCount <= minIdle) {
                emptySignal();
            }
        } finally {
            lock.unlock();
        }
    }
discardConnection這里會(huì)通過(guò)JdbcUtils.close(conn)關(guān)閉連接,然后加鎖判斷是否小于等于minIdle,若為true則執(zhí)行emptySignal

小結(jié)

druid會(huì)在prepareStatement或者執(zhí)行prepareStatement出現(xiàn)異常的時(shí)候執(zhí)行conn.handleException,它委托給dataSource.handleConnectionException,后者會(huì)在exceptionSorter.isExceptionFatal(sqlEx)為true時(shí)會(huì)執(zhí)行handleFatalError,handleFatalError方法這里會(huì)執(zhí)行conn.disable(error),然后標(biāo)記requireDiscard為true,最后執(zhí)行discardConnection來(lái)關(guān)閉連接。通過(guò)這樣子來(lái)快速清理不可用的連接,避免連接池的連接不可用。

以上就是druid handleException執(zhí)行流程源碼解析的詳細(xì)內(nèi)容,更多關(guān)于druid handleException執(zhí)行的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java使用poi生成excel的步驟

    java使用poi生成excel的步驟

    2010以上格式使用XSSFWorkBook對(duì)象, 2003格式使用HSSFWorkBook對(duì)象, 其他對(duì)象操作基本一樣,本文重點(diǎn)給大家介紹java使用poi生成excel的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2022-04-04
  • 圖文詳解Java中的序列化機(jī)制

    圖文詳解Java中的序列化機(jī)制

    java中的序列化可能大家像我一樣都停留在實(shí)現(xiàn)Serializable接口上,對(duì)于它里面的一些核心機(jī)制沒(méi)有深入了解過(guò)。本文將通過(guò)示例帶大家深入了解Java中的序列化機(jī)制,需要的可以參考一下
    2022-10-10
  • 基于SpringBoot+Redis實(shí)現(xiàn)分布式鎖

    基于SpringBoot+Redis實(shí)現(xiàn)分布式鎖

    本文主要介紹了基于SpringBoot+Redis實(shí)現(xiàn)分布式鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Java多線程基礎(chǔ)

    Java多線程基礎(chǔ)

    這篇文章主要介紹Java多線程基礎(chǔ),線程是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位,多線程指在單個(gè)程序中可以同時(shí)運(yùn)行多個(gè)不同的線程執(zhí)行不同的任務(wù),下面來(lái)學(xué)習(xí)具體的詳細(xì)內(nèi)容
    2021-10-10
  • MyBatis延遲加載策略深入探究

    MyBatis延遲加載策略深入探究

    本文主要為大家詳細(xì)介紹下mybatis的延遲加載,從原理上介紹下怎么使用、有什么好處能規(guī)避什么問(wèn)題。感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-07-07
  • Javabean基于xstream包實(shí)現(xiàn)轉(zhuǎn)XML文檔的方法

    Javabean基于xstream包實(shí)現(xiàn)轉(zhuǎn)XML文檔的方法

    這篇文章主要介紹了Javabean基于xstream包實(shí)現(xiàn)轉(zhuǎn)XML文檔的方法,結(jié)合具體實(shí)例形式分析了xstream包用于轉(zhuǎn)換xml文件的具體使用技巧,需要的朋友可以參考下
    2017-05-05
  • SpringMVC使用自定義驗(yàn)證器進(jìn)行數(shù)據(jù)驗(yàn)證的方法

    SpringMVC使用自定義驗(yàn)證器進(jìn)行數(shù)據(jù)驗(yàn)證的方法

    SpringMVC?提供了強(qiáng)大的數(shù)據(jù)驗(yàn)證機(jī)制,可以方便地驗(yàn)證表單提交的數(shù)據(jù),除了自帶的驗(yàn)證器之外,SpringMVC?還支持自定義驗(yàn)證器,允許開(kāi)發(fā)者根據(jù)業(yè)務(wù)需求自定義驗(yàn)證規(guī)則,本文將介紹如何在?SpringMVC?中使用自定義驗(yàn)證器
    2023-07-07
  • Java FTPClient實(shí)現(xiàn)文件上傳下載

    Java FTPClient實(shí)現(xiàn)文件上傳下載

    這篇文章主要為大家詳細(xì)介紹了Java FTPClient實(shí)現(xiàn)文件上傳下載的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • 從0構(gòu)建Oauth2Server服務(wù)之Refreshing-access-tokens

    從0構(gòu)建Oauth2Server服務(wù)之Refreshing-access-tokens

    這篇文章主要為大家介紹了從0構(gòu)建Oauth2Server服務(wù)之Refreshing-access-tokens刷新令牌示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 使用SpringBoot讀取Windows共享文件的代碼示例

    使用SpringBoot讀取Windows共享文件的代碼示例

    在現(xiàn)代企業(yè)環(huán)境中,文件共享是一個(gè)常見(jiàn)的需求,Windows共享文件夾(SMB/CIFS協(xié)議)因其易用性和廣泛的兼容性,成為了許多企業(yè)的首選,在Java應(yīng)用中,尤其是使用Spring Boot框架時(shí),如何讀取Windows共享文件是一個(gè)值得探討的話題,本文介紹了使用SpringBoot讀取Windows共享文件
    2024-11-11

最新評(píng)論

噶尔县| 曲阳县| 天门市| 邹城市| 名山县| 应用必备| 荔浦县| 永川市| 沙雅县| 雅安市| 大冶市| 叙永县| 舒城县| 济源市| 依安县| 深州市| 武陟县| 克东县| 林芝县| 阿拉善左旗| 阿勒泰市| 大新县| 海晏县| 黎城县| 千阳县| 昌都县| 穆棱市| 台中市| 南郑县| 迁安市| 晋宁县| 玛沁县| 鹿邑县| 台江县| 玉山县| 沁阳市| 台中市| 弥勒县| 广水市| 启东市| 壶关县|