POOLED和UNPOOLED源码分析

一.在哪用

  Mybatis 中也有连接池技术:但是它采用的是自己的连接池技术。在 Mybatis 的 SqlMapConfig.xml 配置文件中,通过<dataSource type=”pooled”>来实现 Mybatis 中连接池的配置。

    Mybatis 将它自己的数据源分为三类:   

        • UNPOOLED 不使用连接池的数据源 
        • POOLED 使用连接池的数据源
        •  JNDI  使用 JNDI 实现的数据源`

    具体的结构如下: 

                 

    相应地,MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource、 PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源。

    我们的数据源配置就是在 SqlMapConfig.xml 文件中,具体配置如下:

        

<!-- 配置数据源(连接池)信息 -->
<dataSource type="POOLED">  
    <property name="driver" value="${jdbc.driver}"/> 
    <property name="url" value="${jdbc.url}"/> 
    <property name="username" value="${jdbc.username}"/> 
    <property name="password" value="${jdbc.password}"/> 
</dataSource> 

 

    MyBatis 在初始化时,根据<dataSource>的 type 属性来创建相应类型的的数据源 DataSource,即:

        • type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
        • type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
        • type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用

  同时我们可以在IDEA工具中通过不同的连接,看日志信息再一次验证:

  

二、UNPOOLED源码分析

    根据上面的说明,可以看出源码要在UnpooledDataSource 中查看,IDEA中Ctrl+N 搜索UnpooledDataSource 类:

       

     在UnpooledDataSource 类查找如图的方法,可以看出在这个方法中先创建了一个Properties对象,这个对象是用来专门配置属性的对象,在这之后添加了配置数据库连接的username和password属性,并调用了doGetConnection方法(方法就是下面那个)。

     在第二个doGetConnection方法中,第二行和第三行明显在获取连接并且返回连接。那么接下来让我们查看第一行initializeDriver()代码:

        

      可以看出 ,这个类就是在注册驱动。

    由此已经可以看出来UNPOOLED的实现原理就是普通的JDBC.

 

三.POOLED源码分析:

     在此之前我们需要先明确,POOLED是使用连接池的数据源,这里我们需要明确连接池的一些概念:

        连接池就是用于存储连接的一个容器
        容器其实就是一个集合对象,该集合必须是线程安全的,不能两个线程拿到统一连接

    集合对象、线程安全是必须的,在源码中也会有很大的体现。

    好了,让我们查看PooledDataSource 类,IDEA中Ctrl+N 搜索PooledDataSource 类:

    在PooledDataSource 类查看getConnection方法:

    

     跟踪popConnection方法:

     

    判断是否在线程池中是否由空闲连接:if (!this.state.idleConnections.isEmpty()) 

    如果有,就直接从线程池中获取第一个:conn = (PooledConnection)this.state.idleConnections.remove(0); 

    这里的idleConnections就是一个放置连接的集合:protected final List<PooledConnection> idleConnections = new ArrayList();

    如果没有,判断另外一个已使用池中的最大连接数量是否大于当前的使用连接数量:else if (this.state.activeConnections.size() < this.poolMaximumActiveConnections) 

    最后的else是当前线程池没有控线连接且已使用池连接数量大于设定的最大值,调用最开始(Oldest)的一个连接:long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();

  

四.总结

  • UNPOOLED 不使用连接池的数据源 
  • POOLED 使用连接池的数据源

 

posted @ 2020-04-29 14:56  西希筱梦  阅读(684)  评论(0编辑  收藏  举报