// 数据库连接可用性测试
protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn) {
    String sqlFile = JdbcSqlStat.getContextSqlFile();
    String sqlName = JdbcSqlStat.getContextSqlName();

    if (sqlFile != null) {
        JdbcSqlStat.setContextSqlFile(null);
    }
    if (sqlName != null) {
        JdbcSqlStat.setContextSqlName(null);
    }
    try {
        // checker 不为空
        if (validConnectionChecker != null) {
            // checker 是 init(主流程2)里通过驱动进行适配的检测者,因为本篇文章基于 mysql,所以假设这里适配到的 checker 是 MySqlValidConnectionChecker 类型的
            boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
            long currentTimeMillis = System.currentTimeMillis();
            if (holder != null) {
                holder.lastValidTimeMillis = currentTimeMillis;
                holder.lastExecTimeMillis = currentTimeMillis;
            }

            if (valid && isMySql) { // unexcepted branch
                // 这里在现有驱动版本的情况下拿到的 lastPacketReceivedTimeMs 始终小于0,因为找不到 com.mysql.jdbc.MySQLConnection
                long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
                if (lastPacketReceivedTimeMs > 0) {
                    long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
                    if (lastPacketReceivedTimeMs > 0 //
                            && mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
                        discardConnection(holder);
                        String errorMsg = "discard long time none received connection. "
                                + ", jdbcUrl : " + jdbcUrl
                                + ", version : " + VERSION.getVersionNumber()
                                + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
                        LOG.warn(errorMsg);
                        return false;
                    }
                }
            }

            if (valid && onFatalError) {
                lock.lock();
                try {
                    if (onFatalError) {
                        onFatalError = false;
                    }
                } finally {
                    lock.unlock();
                }
            }

            // 返回验证结果
            return valid;
        }

        if (conn.isClosed()) {
            return false;
        }

        // checker 为空时,就直接利用 validationQuery 进行常规测试
        if (null == validationQuery) {
            // validationQuery 为空就单纯返回 true
            return true;
        }

        Statement stmt = null;
        ResultSet rset = null;
        try {
            stmt = conn.createStatement();
            if (getValidationQueryTimeout() > 0) {
                stmt.setQueryTimeout(validationQueryTimeout);
            }
            rset = stmt.executeQuery(validationQuery);
            if (!rset.next()) {
                // 执行检测语句失败,返回 false
                return false;
            }
        } finally {
            // 关闭资源
            JdbcUtils.close(rset);
            JdbcUtils.close(stmt);
        }

        if (onFatalError) {
            lock.lock();
            try {
                if (onFatalError) {
                    onFatalError = false;
                }
            } finally {
                lock.unlock();
            }
        }

        // 验证通过返回 true
        return true;
    } catch (Throwable ex) {
        // skip
        return false;
    } finally {
        if (sqlFile != null) {
            JdbcSqlStat.setContextSqlFile(sqlFile);
        }
        if (sqlName != null) {
            JdbcSqlStat.setContextSqlName(sqlName);
        }
    }
}

// MySqlValidConnectionChecker 类里的验证方法
public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {
    if (conn.isClosed()) {
        return false;
    }

    // 是否启用 ping 方法(如果驱动程序有该方法,则这里为 true,一般情况下都是 true)
    if (usePingMethod) {
        if (conn instanceof DruidPooledConnection) {
            conn = ((DruidPooledConnection) conn).getConnection();
        }

        if (conn instanceof ConnectionProxy) {
            conn = ((ConnectionProxy) conn).getRawObject();
        }

        if (clazz.isAssignableFrom(conn.getClass())) {
            if (validationQueryTimeout <= 0) {
                validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
            }

            try {
                // ping 对象是初始化时拿到驱动程序的一个 Method 对象,这里通过 invoke 触发调用
                ping.invoke(conn, true, validationQueryTimeout * 1000);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof SQLException) {
                    throw (SQLException) cause;
                }
                // ping 出错抛异常
                throw e;
            }
            // 通过则返回 true
            return true;
        }
    }

    // 如果不支持 ping 方式检测,则触发 SELECT 1 的方式进行检测(一般情况下不会触发,都是上面 ping 方式)
    String query = validateQuery;
    if (validateQuery == null || validateQuery.isEmpty()) {
        query = DEFAULT_VALIDATION_QUERY;
    }

    Statement stmt = null;
    ResultSet rs = null;
    try {
        stmt = conn.createStatement();
        if (validationQueryTimeout > 0) {
            stmt.setQueryTimeout(validationQueryTimeout);
        }
        rs = stmt.executeQuery(query);
        return true;
    } finally {
        JdbcUtils.close(rs);
        JdbcUtils.close(stmt);
    }

}