源码中文注释:https://github.com/tuguangquan/mybatis,需结合下载的源码。
mybatis 不但能集成第三方数据源组件,自身也提供了数据源的实现。
先看一下mybatis源码的目录结构:
从结构目录就可以知道mybatis 提供了集成第三方组件的类:JndiDataSourceFactory
以及自身提供的数据源实现:池化的 “pooled” 和非池化的“unpooled”
所谓实现数据源,其实就是生产connection。
1、mybati 实现数据源
工厂接口:DataSourceFactory,工厂类公共接口。
public interface DataSourceFactory {
//设置属性,被XMLConfigBuilder所调用
void setProperties(Properties props);
//生产数据源,直接得到javax.sql.DataSource
DataSource getDataSource();
}
1.1 非池化数据源实现(unpooled目录下)
非池化的数据源实现本质上其实就是我们的jdbc连接数据的,加载数据库驱动Driver,然后根据Driver 获取连接connection。
分为池化和非池化数据源,采用的是工厂模式生产datasource.
工厂类:UnpooledDataSourceFactory(实现了DataSourceFactory接口)
目标对象:UnpooledDataSource(实现了javax.sql.DataSource 接口)
1.1.1 UnpooledDataSourceFactory工厂
实现DataSourceFactory 接口的方法,生产UnpooledDataSource 对象。
1、拥有一个无参构造,构造执行 new UnpooledDataSource。
2、getDataSource()方法,返回在构造函数中初始化过的dataSource
3、setProperties() 方法,set到元对象 MetaObject 中去
1.1.2 UnpooledDataSource
初始化数据库驱动 DriverManager ,根据url,username,password等数据库连接信息创建connection。
1、很多不同的构造方法,接收 url,username,password,Properities等
2、私有的 sychronized initializaDriver() 方法(本质:driver=Class.forName(....)),把产生的Driver封装在
一个 statis 的ConcurrentHashMap()中。
3、getConnection 方法,调用 doGetConnection(Properties propertiews)获取到connection,然后经过configuretionConnection(Connection conn) 方法设置事务级别与是否自动提交,
1.2 池化数据源(pooled目录下)
是基于非池化数据源实现的。
PooledDataSourceFactory:继承UnpooledDataSourceFactory(非池化工厂类)
PooledConnection:使用动态代理封装了真正的数据库连接对象
PoolState:用于管理PooledConnection对象状态的组件,通过两个list分别管理空闲状态的连接资源和活跃状态的连接资源
PooledDataSource:一个简单,同步的、线程安全的数据库连接池 。
1.2.1 PooledDataSourceFactory
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
//数据源换成了PooledDataSource
public PooledDataSourceFactory() {
this.dataSource = new PooledDataSource();
}
}
1.2.2 PoolState
1、拥有一个PooledDataSource;
2、两个list:存放空闲连接:idleConnection;存放活跃连接:activeConnections
3、有参(参数:PooledDataSource )构造方法:获得一个PooledDataSource。
4、获得PooledConnection 的一些状态信息:请求次数、总请求时间、总等待时间、要等待的次数、坏的连接次数等,获得这些数据的方法都是synchronized。
1.2.3 PooledDataSource
拥有PoolState,UnpooledDataSource,以及其他属性:正在使用的链接数、空闲连接数、被检查的时间等
1、多个构造函数,初始化UnpooledDataSource,并且根据url,username,password 生成相应的hashcode。
2、getConnection() 方法,调用popConnection(),从PoolState 中取出一个有效的connection。
3、forceCloseAll()方法,关闭所有的connection(activeConnections、idleConnections)。实现了同步:synchronized(PoolState)
4、pushConnection(),实现了同步:synchronized(PoolState)。
5、popConnection(),实现了同步:synchronized(PoolState)。
6、pingConnection(pooledConnection conn),核对一个pooledConnection 是否可用.
7、static unwrapConnection(Connection conn),从代理Connection 中获取到一个真实的Connection.
8、finalize(),调用forceCloseAll()和super.finalize().
获取和归还连接过程
popConnection():
pushConnection()
1.2.4 PooledConnection
实现了InvocationHandler,提供动态代理。
1、有参构造,接收一个Connection 和一个PooledDataSource 对象。
惟一的有参构造:
public PooledConnection(Connection connection, PooledDataSource dataSource) {
//每个PooledConnection 都拥有自己的hashCode,用来判定是否是同一个PooledConnection
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);
}
2、JNDI 数据源工厂
这个数据源的实现是为了使用如Spring 或应用服务器这类的容器,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。
实现接口DataSource