软件编程
位置:首页>> 软件编程>> java编程>> 详解Mybatis中的PooledDataSource

详解Mybatis中的PooledDataSource

作者:周杰伦本人  发布时间:2022-10-24 18:08:11 

标签:Mybatis,PooledDataSource

前言

上篇Java Mybatis数据源之工厂模式文章中我们介绍了Mybatis的数据源模块的DataSource接口和它对应的实现类UnpooledDataSource、PooledDataSource,这篇文章详细介绍一下PooledDataSource
PooledDataSource使用了数据库连接池可以实现数据库连接池的重复利用,还能控制连接数据库的连接上限,实现数据库连接的统一管理,缓存数据连接信息还能防止流量突发连接数据库不及时

PooledDataSource有个PoolState状态,PoolState里保存着数据库连接信息PooledConnection,PooledConnection实现InvocationHandler接口,重写invoke方法,显然这是一个代理类,使用了JDK的 *

PooledConnection

class PooledConnection implements InvocationHandler {
   private static final Class<?>[] IFACES = new Class<?>[] { Connection.class };
   public PooledConnection(Connection connection, PooledDataSource dataSource) {
       this.hashCode = connection.hashCode();
       this.realConnection = connection;
       this.dataSource = dataSource;
       this.createdTimestamp = System.currentTimeMillis();
       this.lastUsedTimestamp = System.currentTimeMillis();
       this.valid = true;
       this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
   }

@Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       String methodName = method.getName();
       if (CLOSE.equals(methodName)) {
           dataSource.pushConnection(this);
           return null;
       }
       try {
           if (!Object.class.equals(method.getDeclaringClass())) {
               checkConnection();
           }
           return method.invoke(realConnection, args);
       } catch (Throwable t) {
           throw ExceptionUtil.unwrapThrowable(t);
       }
   }
}

我们看一看到构造方法中调用了Proxy.newProxyInstance()方法来生成代理类,而重写invoke方法中如果是close()就调用pushConnection()方法直接把它放入连接池而不是关闭连接,其他情况调用checkConnection()检查连接信息,代理类调用realConnection()方法,下面就看一下pushConnection()方法

PooledDataSource的pushConnection()方法

方法的功能就是把数据库连接放入连接池中:

protected void pushConnection(PooledConnection conn) throws SQLException {
       synchronized (state) {
           state.activeConnections.remove(conn);
           if (conn.isValid()) {
               if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {
                   state.accumulatedCheckoutTime += conn.getCheckoutTime();
                   if (!conn.getRealConnection().getAutoCommit()) {
                       conn.getRealConnection().rollback();
                   }
                   PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
                   state.idleConnections.add(newConn);
                   newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
                   newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
                   conn.invalidate();
                   if (log.isDebugEnabled()) {
                       log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
                   }
                   state.notifyAll();
               } else {

state.accumulatedCheckoutTime += conn.getCheckoutTime();
                   if (!conn.getRealConnection().getAutoCommit()) {
                       conn.getRealConnection().rollback();
                   }
                   conn.getRealConnection().close();
                   if (log.isDebugEnabled()) {
                       log.debug("Closed connection " + conn.getRealHashCode() + ".");
                   }
                   conn.invalidate();
               }
           } else {
               if (log.isDebugEnabled()) {
                   log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
               }
               state.badConnectionCount++;
           }
       }
   }
  • 从活跃连接集合中删除该连接

  • 如果PooledConnection有效,并且空闲连接数小于最大空闲连接数,就利用当前PooledConnection创建PooledConnection,放入空闲连接数集合中,方便下次使用,关闭当前PooledConnection对象的数据库连接,并对当前PooledConnection对象设置无效,最后唤醒其他等待的线程。如果空闲连接数大于最大空闲连接数了就关闭连接,设置当前连接无效

  • 如果PooledConnection无效,badConnectionCount加一,这个badConnectionCount是记录无效的数据库连接信息的

来源:https://blog.51cto.com/u_15460453/5375552

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com