mybaits源码分析(四) 数据源
前言:对于ORM框架,数据源都是不可或少的组件,虽然mybaits框架整合spring时,可以由外部指定数据源对象,构建到SqlSessionFactoryBean中,但是对于mybaits自身对数据源的实现原理还是值得探究的,本文将通过对MyBatis框架的数据源 结构进行详尽的分析,并且深入解析MyBatis的连接池。
本文内容初步分为下面几个部分
mybaits数据源的概述
mybaits数据源的构建和使用
UnpooledDataSource的剖析
PooledDataSource的剖析
简易数据源案例演示
一、Mybaits数据源的概述
1、数据源分类
MyBatis把数据源DataSource分为三种
UnpooledDataSource :不使用连接池的数据源
PooledDataSource :使用连接池的数据源
JndiDataSource:使用JNDI实现的数据源
2、数据源类结构
数据源由DatasourceFacotry创建,UnpooledDataSourceFacotry创建UnpooledDataSource ,PooledDataSourceFacotry创建PooledDataSource ,并且UnpooledDataSourceFacotry继承UnpooledDataSourceFacotry用于通用设置属性用途,PooledDataSource 内部维护了UnpooledDataSource 的实例,用于真实创建数据库链接, PooledDataSource 内部连接池缓存的是用于增强并包装真实连接对象和代理连接对象的PooledConnection。
类结构如下:
3、数据源的创建
我们主要讲解UnpooledDataSource和PooledDataSource,其中UnpooledDataSource是没有使用连接池的数据源,PooledDataSource包装了UnpooledDataSource,并且扩展了连接池功能,用UnpooledDataSource依据创建连接,内部用列表容器实现连接池功能。
数据源的创建,采用了工厂模式,UnpooledDataSource和PooledDataSource的创建,分别交于不同的实现了DataSourceFactory的工厂类创建,并且设置了一些配置属性。下面是UnpooledDataSourceFactory创建数据源的过程。
public UnpooledDataSourceFactory() { // 构造函数创建对应工厂的数据源
this.dataSource = new UnpooledDataSource();
}
public void setProperties(Properties properties) { // 设置属性
Properties driverProperties = new Properties();
MetaObject metaDataSource = SystemMetaObject.forObject(dataSource);
for (Object key : properties.keySet()) {
String propertyName = (String) key;
if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) { // 设置驱动属性
String value = properties.getProperty(propertyName);
driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);
} else if (metaDataSource.hasSetter(propertyName)) { // 其他常规数据,依据有无set方法进行设置
String value = (String) properties.get(propertyName);
Object convertedValue = convertValue(metaDataSource, propertyName, value);
metaDataSource.setValue(propertyName, convertedValue);
} else {
throw new DataSourceException("Unknown DataSource property: " + propertyName);
}
}
if (driverProperties.size() > 0) {
metaDataSource.setValue("driverProperties", driverProperties);
}
}
二、mybaits数据源的构建
上面对数据源的分类,类图结构,以及工厂类创建数据源的过程进行了简单的介绍,知道框架会根据不同的工厂类创建不同的数据源,那么在mybaits中如何创建数据源工厂类的呢
1、数据源的构建
下面是xml配置文件
<dataSource type="POOLED">
<property name="driver" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</dataSource>
数据源创建的时候,会根据dataSource节点的type属性,实例化对应的工厂类,进行数据源的创建,并且把子节点的props属性对添加到数据源的set方法中,POOLED表示会创建PooledDataSource数据源,Unpooled表示会创建UnpooledDataSource数据源。
private DataSourceFactory dataSourceElement(XNode context) throws Exception {
if (context != null) { // context是解析dataSource节点的内容
String type = context.getStringAttribute("type"); // type属性
Properties props = context.getChildrenAsProperties(); // 子属性键值对
DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance();
factory.setProperties(props);
return factory;
}
throw new BuilderException("Environment declaration requires a DataSourceFactory.");
}
2、数据源的使用
数据源的作用就是获取连接对象connection,那么在执行过程中,我们是哪个时候从数据源中获取连接对象的呢?从上篇事务我们了解到,连接是包装到Transaction对象中,当我们创建了SQLSession之后,通过SqlSessio