本文需要配合代码demo一起观看更佳,源码地址。
本源码中对 mybatis代码做了详尽的注释。对mybatis源码进行了详尽的注释,且可以对项目进行install,然后在ron-man-mybatis1项目中 src/main/java/iron/man/lyf/ironmanmybatis1/run_test/MybatisQuickStart.java 进行运行 对mybatis源码进行debug查看运行过程,欢迎大家下载指正。如果您觉得帮助到您麻烦给个赞
datasource下的两个包一个是不使用连接池、一个是使用mybatis提供的连接池
此dataSource是使用的工厂模式创建的。
抽象工厂: DataSourceFactory是抽象工厂
具体工厂:pooled
和unpooled
两个包中的UnpooledDataSourceFactory
和PooledDataSourceFactory
是抽象工厂的两个实现类。PooledDataSourceFactory继承了UnPooledDataSourceFactory
。两个类基本一模一样,只不过PooledDataSourceFactory中实例化的是PooledDataSource
,UnPooledDataSourceFactory
中实例化的是UnPooledDataSource
。所以会看到在使用mybatis默认连接池的时候,却会时常调用UnPooledDataSourceFactory
的方法。实际是由于UnPooledDataSourceFactory继承了UnPooledDataSourceFactory
全部方法的缘故
抽象产品:工厂要生产的对象的抽象类是jdk 的 /javax/sql/DataSource
具体产品:pooled
和unpooled
两个包中 的UnpooledDataSource、PooledDataSource
是jdk 的 DataSource
的两个实现类
可以把DataSource 的实现类看做一个手写的jdbc连接数据库的实现类(iron-man-mybatis/iron-man-mybatis1/src/main/java/iron/man/lyf/ironmanmybatis1/run_test/JdbcDemo.java)
UnpooledDataSource
中,只不过是把driver、url、username、password…这些连接参数提成了成员变量,由程序从配置文件读取然后给这些变量赋值。然后就是构造器多了一点,还有一些get、set方法干扰。最后就是initializeDriver加载驱动、doGetConnection
从jdk拿去数据库链接Connection
,与JdbcDemo
的数据库连接无异。PooledDataSource
会把 UnpooledDataSource
放到属性中,是为了重复使用UnpooledDataSource
中的driver、url、username、password…这些字段。PooledDataSource
会存一些 最大活跃连接数
、最大闲置连接数
等这些固定的值,而 PoolState 属性会存程序运行起来的一些值,譬如:空闲的连接池资源集合
、活跃的连接池资源集合
等。值得注意的是PoolState.toString()会返回当前连接池的一堆关键参数每创建一个sqlSession就会进行一次数据库连接操作。由:iron-man-mybatis/iron-man-mybatis1/src/main/java/iron/man/lyf/ironmanmybatis1/run_test/CacheTest.java#Test1LevelCache 可得知。此demo创建了两个sqlsession,进行了两次数据库连接。
在src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java 类中的popConnection
、pushConnection
、pingConnection
方法点断点,结合demo:CacheTest.java#Test1LevelCache 即可看到连接池运行的全貌
popConnection
是负责在开启一个新的sqlsession需要一个数据库连接的时候弹出来一个数据库连接。其中还会操作idleConnections(空闲的连接池资源集合)
、activeConnections(活跃的连接池资源集合)
等状态。
pushConnection
是在关闭sqlsession,需要把这个数据库连接归还连接池时候进行调用。期间也会操作idleConnections(空闲的连接池资源集合)
、activeConnections(活跃的连接池资源集合)
等状态。
pingConnection
是在popConnection
时需要有一个验证当前连接是否有效,如果在mybatis 的配置文件 environments
属性中配置了 poolPingEnabled
为true,那么就会在pingConnection
进行一个数据库查询的操作,查询的sql是在environments
属性中配置的 poolPingQuery
的sql。
/datasource/pooled/PooledConnection.java 是用对Connection做的一个动态代理增强。
其主要作用是:
pushConnection
方法。注意点:
popConnection
内创建的PooledConnection
只是一个外壳,真正的connection 是PooledConnection
内部的 realConnection
checkoutTimestamp
为当前时间,这个值在超时判断中起决定作用PooledConnection
外壳,真正的realConnection
不会移除只是放到新创建的PooledConnection
新的外壳中。当来一个连接请求会先看连接池有没有空闲的连接,有的话直接返回空闲连接。
如果没有空闲连接。
判断当前活跃的连接数是否到了最大连接数。
验证连接
如果验证通过,那么进一步初始化PooledConnection。并修改一些状态值
2. 如果验证不通过,即连接无效。那么badConnectionCount(累计的获取无效连接次数+1)