本文我们来给大家介绍了MyBatis中的DataSource的设计实现。其实蛮容易的哦。
DataSource
首先大家要清楚DataSource属于MyBatis三层架构设计的基础层
然后我们来看看具体的实现。
在数据持久层中,数据源是一个非常重要的组件,其性能直接关系到整个数据持久层的性能,在实际开发中我们常用的数据源有 Apache Common DBCP,C3P0,Druid 等,MyBatis不仅可以集成第三方数据源,还提供的有自己实现的数据源。
在MyBatis中提供了两个 javax.sql.DataSource 接口的实现,分别是 PooledDataSource 和 UnpooledDataSource .
1 DataSourceFactory
DataSourceFactory是用来创建DataSource对象的,接口中声明了两个方法,作用如下
public interface DataSourceFactory {
// 设置 DataSource 的相关属性,一般紧跟在初始化完成之后
void setProperties(Properties props);
// 获取 DataSource 对象
DataSource getDataSource();
}
DataSourceFactory接口的两个具体实现是 UnpooledDataSourceFactory 和 PooledDataSourceFactory 这两个工厂对象的作用通过名称我们也能发现是用来创建不带连接池的数据源对象和创建带连接池的数据源对象,先来看下 UnpooledDataSourceFactory 中的方法
/**
* 完成对 UnpooledDataSource 的配置
* @param properties 封装的有 DataSource 所需要的相关属性信息
*/
@Override
public void setProperties(Properties properties) {
Properties driverProperties = new Properties();
// 创建 DataSource 对应的 MetaObject 对象
MetaObject metaDataSource = SystemMetaObject.forObject(dataSource);
// 遍历 Properties 集合,该集合中配置了数据源需要的信息
for (Object key : properties.keySet()) {
String propertyName = (String) key; // 获取属性名称
if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) {
// 以 "driver." 开头的配置项是对 DataSource 的配置
String value = properties.getProperty(propertyName);
driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);
} else if (metaDataSource.hasSetter(propertyName)) {
// 有该属性的 setter 方法
String value = (String) properties.get(propertyName);
Object convertedValue = convertValue(metaDataSource, propertyName, value);
// 设置 DataSource 的相关属性值
metaDataSource.setValue(propertyName, convertedValue);
} else {
throw new DataSourceException("Unknown DataSource property: " + propertyName);
}
}
if (driverProperties.size() > 0) {
// 设置 DataSource.driverProperties 的属性值
metaDataSource.setValue("driverProperties", driverProperties);
}
}
UnpooledDataSourceFactory的getDataSource方法实现比较简单,直接返回DataSource属性记录的 UnpooledDataSource 对象
2 UnpooledDataSource
UnpooledDataSource 是 DataSource接口的其中一个实现,但是 UnpooledDataSource 并没有提供数据库连接池的支持,我们来看下他的具体实现吧
声明的相关属性信息
private ClassLoader driverClassLoader; // 加载Driver的类加载器
private Properties driverProperties; // 数据库连接驱动的相关信息
// 缓存所有已注册的数据库连接驱动
private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<>();
private String driver; // 驱动
private String url; // 数据库 url
private String username; // 账号
private String password; // 密码
private Boolean autoCommit; // 是否自动提交
private Integer defaultTransactionIsolationLevel; // 事务隔离级别
private Integer defaultNetworkTimeout;
然后在静态代码块中完成了 Driver的复制
static {
// 从 DriverManager 中获取 Drivers
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
// 将获取的 Driver 记录到 Map 集合中
registeredDrivers.put(driver.getClass().getName(), driver);
}
}
UnpooledDataSource 中获取Connection的方法最终都会调用 doGetConnection() 方法。
<