vlambda博客
学习文章列表

MyBatis连接池底层原理探究

概述

我们在实际开发中都会使用连接池,因为它可以减少我们获取连接所消耗的时间。简单来说,连接池就是用于存储连接的一个容器,容器其实就是一个集合对象,该集合必须是线程安全的,不能两个线程拿到同一连接。同时该集合还必须实现队列的特性:先进先出。



MyBatis连接池原理

  • 配置的位置:

    主配置文件SqlMapConfig.xml中的dataSource标签,type属性表示采用何种连接池方式。

  • MyBatis连接池提供了三种方式的配置:

  1. POOLED:

    采用传统的javax.Sql.DataSource规范中的连接池,MyBatis有针对规范的连接;(简单来说,使用POOLED,就是从池中获取一个连接)

  2. UNPOOLED:

    采用传统的获取连接的方式,虽然也实现javax.Sql.DataSource接口,但是并没有使用池的思想;(使用UNPOOLED,每次都创建一个新连接)

  3. JNDI:

    采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到的DataSource不同。但注意,如果不是web或maven的war工程,是不能使用的。



UNPOOLED分析池

public interface DataSource extends CommonDataSource,Wrapper{ Connection getConnection() throws SQLException;}
public class UnpooledDataSource implements DataSource{ @Override public Connection getConnection() throws SQLException{ return doGetConnection(username,password); }  private Connection doGetConnection(String username,String password) throws SQLException{   //省略其他代码   return doGetConnection(props);  }  private Connection doGetConnection(Properties properties) throws SQLException{   //注册驱动   initializeDriver();   //获取连接    Connection connection = DriverManger.getConnection(url,properties);    configureConnection(connection);    return connection;  }  private synchronized void initializeDriver() throws SQLException{    //...  }}



POOLED分析

public interface DataSource extends CommonDataSource,Wrapper{ Connection getConnection() throws SQLException;}
public class PooledDataSource implements DataSource{ @Override  public Connection getConnection() throws SQLException{    return popConnection(dataSource.getUsername(),dataSource.getPassword()).getProxyConnection; } private PooledConnection popConnection(String username,String password) throws SQLException{ //省略其他代码    while(conn == null){      synchronized(state){       if(!state.idleConnections.isEmpty()){//空闲连接还有          conn = state.idleConnections.remove(0);        }else{          if(state.activeConnections.size()< poolMaximumActiveConnections){             conn = new PooledConnection(dataSource.getConnection(),this);         }else{            PooledConnection oldestActiveConnection = state.activeConnections.get(0);         }        }      } }  }}
此时涉及到两个池:一个是空闲池,另一个是活动池。如果空闲池中没有连接,再看活动池。如果活动连接池的最大数量小于设定的最大值,则创建一个连接,否则,获取活动连接池中最先进来的那个连接(oldest)。



后记

     若有错误或者不当之处,可与作者联系,以便一起学习改正!




如果你喜欢本文,

请长按二维码,关注 Jianghq