工厂方法模式最终也是符合“开放-封闭”原则的,可以通过添加新的 Factory 接口实现和 Product 接口实现来扩展整个体系的功能 。

MyBatis 的数据源模块也是用到了工厂方法模式,如果需要扩展新的数据源实现时,只需要添加对应的 Factory 实现类,新的数据源就可以被 MyBatis 使用。

DataSourceFactory接口及其实现

DataSource及实现

 全局配置文件的mybatis-config.xml

 解析全局配置文件的mybatis-config.xml

 

看一下,数据库连接池的几个关键方法

1. 获取连接

2.创建连接,通过class PooledConnection implements InvocationHandler动态创建

主要是拦截Close方法

 

 3.PooledDataSource的核销方法 push和pop

 

private PooledConnection popConnection(String username, String password) throws SQLException {

    while (conn == null) {

        synchronized (state) { // 加锁同步

            // 步骤1:检测空闲连接集合

            if (!state.idleConnections.isEmpty()) { 

                // 获取空闲连接

                conn = state.idleConnections.remove(0);

            } else { // 没有空闲连接

                // 步骤2:活跃连接数没有到上限值,则创建新连接

                if (state.activeConnections.size() < poolMaximumActiveConnections) {

                    // 创建新数据库连接,并封装成PooledConnection对象

                    conn = new PooledConnection(dataSource.getConnection(), this);

                } else {// 活跃连接数已到上限值,则无法创建新连接

                    // 步骤3:检测超时连接

                    // 获取最早的活跃连接

                    PooledConnection oldestActiveConnection = state.activeConnections.get(0);

                    long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();

                    // 检测该连接是否超时

                    if (longestCheckoutTime > poolMaximumCheckoutTime) {

                        // 对超时连接的信息进行统计

                        state.claimedOverdueConnectionCount++;

                        state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;

                        state.accumulatedCheckoutTime += longestCheckoutTime;

                        // 将超时连接移出activeConnections集合

                        state.activeConnections.remove(oldestActiveConnection);

                        // 如果超时连接上有未提交的事务,则自动回滚

                        if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {

                            try {

                                oldestActiveConnection.getRealConnection().rollback();

                            } catch (SQLException e) {

                            }

                        }

                        // 创建新PooledConnection对象,但是真正的数据库连接

                        conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);

                        conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());

                        conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());

                        // 将超时PooledConnection设置为无效

                        oldestActiveConnection.invalidate();

                    } else {

                        // 步骤4:无空闲连接、无法创建新连接且无超时连接,则只能阻塞等待

                        if (!countedWait) { // 统计阻塞等待次数

                            state.hadToWaitCount++;

                            countedWait = true;

                        }

                        long wt = System.currentTimeMillis();

                        state.wait(poolTimeToWait);// 阻塞等待

                        // 统计累积的等待时间

                        state.accumulatedWaitTime += System.currentTimeMillis() - wt;

                    }

                }

            }

            if (conn != null) { // 对连接进行统计

                if (conn.isValid()) { // 检测PooledConnection是否有效

                    // 配置PooledConnection的相关属性,设置connectionTypeCode、checkoutTimestamp、lastUsedTimestamp字段的值

                    conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));

                    conn.setCheckoutTimestamp(System.currentTimeMillis());

                    conn.setLastUsedTimestamp(System.currentTimeMillis());

                    state.activeConnections.add(conn); // 添加到活跃连接集合

                    state.requestCount++;

                    state.accumulatedRequestTime += System.currentTimeMillis() - t;

                } else { 

                    ... ...// 统计失败的情况

                }

            }

        }

    }

    return conn;

}

protected void pushConnection(PooledConnection conn) throws SQLException {

    synchronized (state) {

        state.activeConnections.remove(conn); // 步骤1:从活跃连接集合中删除该连接

        if (conn.isValid()) {// 步骤2:检测该 PooledConnection 对象是否可用

            // 步骤3:检测当前PooledDataSource连接池中的空闲连接是否已经达到上限值

            if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {

                // 累计增加accumulatedCheckoutTime

                state.accumulatedCheckoutTime += conn.getCheckoutTime();

                if (!conn.getRealConnection().getAutoCommit()) {

                    // 回滚未提交的事务

                    conn.getRealConnection().rollback();

                }

                // 步骤4:将底层连接重新封装成PooledConnection对象,

                // 并添加到空闲连接集合(也就是前面提到的 idleConnections 集合)

                PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);

                state.idleConnections.add(newConn);

                // 设置新PooledConnection对象的创建时间戳和最后使用时间戳

                newConn.setCreatedTimestamp(conn.getCreatedTimestamp());

                newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());

                conn.invalidate(); // 丢弃旧PooledConnection对象

                // 唤醒所有阻塞等待空闲连接的线程

                state.notifyAll();

            } else {

                // 当前PooledDataSource连接池中的空闲连接已经达到上限值

                // 当前数据库连接无法放回到池中



                // 累计增加accumulatedCheckoutTime

                state.accumulatedCheckoutTime += conn.getCheckoutTime();

                if (!conn.getRealConnection().getAutoCommit()) {

                    // 回滚未提交的事务

                    conn.getRealConnection().rollback();

                }

                // 关闭真正的数据库连接

                conn.getRealConnection().close();

                // 将PooledConnection对象设置为无效

                conn.invalidate(); 

            }

        } else {

            // 统计无效PooledConnection对象个数

            state.badConnectionCount++; 

        }

    }

}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐