// 对外提供的数据源工厂接口
public interface DataSourceFactory {
// 设置配置信息
void setProperties(Properties props);
// 获取数据源
DataSource getDataSource();
}
复制代码
复制代码
// 非池化的数据源工厂类
public class UnpooledDataSourceFactory implements DataSourceFactory {
private static final String DRIVER_PROPERTY_PREFIX = "driver."; // 数据库驱动名前缀
private static final int DRIVER_PROPERTY_PREFIX_LENGTH = DRIVER_PROPERTY_PREFIX.length();
protected DataSource dataSource; // 数据源
public UnpooledDataSourceFactory() {
this.dataSource = new UnpooledDataSource(); // 构造一个非池化的数据源(下文分析数据源详细代码)
}
public void setProperties(Properties properties) { // 对数据源进行配置,此处设计反射包的知识(本章重点不在这,可忽略)
Properties driverProperties = new Properties();
MetaObject metaDataSource = SystemMetaObject.forObject(dataSource); // 将dataSource类转为metaObject类
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); // driverProperties存储数据库驱动参数
} else if (metaDataSource.hasSetter(propertyName)) { // 如果有set方法
String value = (String) properties.get(propertyName);
// 根据属性类型进行类型的转换,主要是 Integer, Long, Boolean 三种类型的转换
Object convertedValue = convertValue(metaDataSource, propertyName, value);
// 设置DataSource 的相关属性值
metaDataSource.setValue(propertyName, convertedValue);
} else {
throw new DataSourceException("Unknown DataSource property: " + propertyName);
}
}
// 设置 DataSource.driverProerties 属性值
if (driverProperties.size() > 0) {
metaDataSource.setValue("driverProperties", driverProperties);
}
}
// 获取数据源
public DataSource getDataSource() {
return dataSource;
}
// 对Integer, Long, Boolean 三种类型的转换
private Object convertValue(MetaObject metaDataSource, String propertyName, String value) {
Object convertedValue = value;
Class<?> targetType = metaDataSource.getSetterType(propertyName);
if (targetType == Integer.class || targetType == int.class) {
convertedValue = Integer.valueOf(value);
} else if (targetType == Long.class || targetType == long.class) {
convertedValue = Long.valueOf(value);
} else if (targetType == Boolean.class || targetType == boolean.class) {
convertedValue = Boolean.valueOf(value);
}
return convertedValue;
}
}
复制代码
复制代码
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
public PooledDataSourceFactory() {
// dataSource实现类变为PooledDataSource
this.dataSource = new PooledDataSource();
}
}
复制代码
unPooledDataSourceFactory主要工作是对数据源进行参数配置,并提供获取数据源方法。分析PooledDataSourceFactory源码,只是继承unPooledDataSourceFactory,将DataSource实现类改变为PooledDataSource。
unPooledDataSource源码分析:基本的数据源实现都实现了DataSource接口,重写获取数据库连接的方法。unPooledDataSource从类名可知,不支持数据库连接的池化。也就是说,每来一个获取连接请求,就新建一个数据库连接。让我们看源码验证下。
复制代码
public class UnpooledDataSource implements DataSource {
private ClassLoader driverClassLoader; // 数据库驱动类加载器
private Properties driverProperties; // 有关数据库驱动的参数
private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<String, Driver>(); // 缓存已注册过的数据库驱动
private String driver; // 数据库驱动
private String url; // 数据库名
private String username; // 连接用户名
private String password; // 密码
private Boolean autoCommit; // 是否自动提交
private Integer defaultTransactionIsolationLevel; // 事物隔离级别
static { // 初始化
Enumeration<Driver> drivers = DriverManager.getDrivers(); // DriverManager中已存在的数据库驱动加载到数据库驱动缓存
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
registeredDrivers.put(driver.getClass().getName(), driver);
}
}
.....
public Connection getConnection() throws SQLException {
return doGetConnection(username, password);
}
// 获取数据库连接
private Connection doGetConnection(Properties properties) throws SQLException {
initializeDriver(); // 初始化数据库驱动
Connection connection = DriverManager.getConnection(url, properties); // 此处每次获取连接,就新建一个数据库连接
configureConnection(connection); // 设置数据库是否自动提交,设置数据库事物隔离级别
return connection;
}
private synchronized void initializeDriver() throws SQLException {
// 若此驱动还没初始化,则进行初始化
if (!registeredDrivers.containsKey(driver)) {
Class<?> driverType;
try {
if (driverClassLoader != null) {
driverType = Class.forName(driver, true, driverClassLoader);
} else {
driverType = Resources.classForName(driver);
}
// DriverManager requires the driver to be loaded via the system ClassLoader.
// http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
Driver driverInstance = (Driver)driverType.newInstance();
DriverManager.registerDriver(new DriverProxy(driverInstance));
registeredDrivers.put(driver, driverInstance);
} catch (Exception e) {
throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
}
}
}
private void configureConnection(Connection conn) throws SQLException {
if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
conn.setAutoCommit(autoCommit);
}
if (defaultTransactionIsolationLevel != null) {
conn.setTransactionIsolation(defaultTransactionIsolationLevel);
}
}
....
}
PoolConnection是一个connection代理类,里面封装了真实的连接与代理连接,现在我们先来分析PoolConnection的源码。
复制代码
class PooledConnection implements InvocationHandler { // 连接代理类
private static final String CLOSE = "close";
private static final Class<?>[] IFACES = new Class<?>[] { Connection.class };
private int hashCode = 0;
private PooledDataSource dataSource; // 数据源
private Connection realConnection; // 被代理的真实连接
private Connection proxyConnection; // 代理连接
private long checkoutTimestamp; // 从连接池中取出连接的时间
private long createdTimestamp; // 连接建立的时间
private long lastUsedTimestamp; // 连接上次使用的时间
private int connectionTypeCode; // 用于标注该连接所在的连接池
private boolean valid; // 连接有效的标志
复制代码
PooledConnection实现了InvocationHandler接口,则可见是一个代理对象。查看属性可知,内部有真实连接与代理连接,并附带连接的一些记录信息。查看该类的构造方法。
复制代码
public PooledConnection(Connection connection, PooledDataSource dataSource) {
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); // 使用动态代理生成连接的代理类
}
/*
* Invalidates the connection
*/
// 将该链接置为无效
public void invalidate() {
valid = false;
}
复制代码
查看构造方法可知,内部除了初始化一些属性外,还将连接的代理类也进行初始化了。那代理类究竟做了什么,查看重写的invoke方法源码。
复制代码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 代理方法
String methodName = method.getName(); // 获取方法名
if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) { // 若是close方法,则将该连接放入数据源中
dataSource.pushConnection(this);
return null;
} else {
try {
if (!Object.class.equals(method.getDeclaringClass())) { // 若要执行的方法不是object方法,则检查连接的有效性
// issue #579 toString() should never fail
// throw an SQLException instead of a Runtime
checkConnection();
}
return method.invoke(realConnection, args); //执行真实的方法
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
private void checkConnection() throws SQLException {
if (!valid) {
throw new SQLException("Error accessing PooledConnection. Connection is invalid.");
}
}
复制代码
由源码可知,代理连接在执行方法时,会先检查此连接的有效性,然后执行真实的方法。分析完PoolConnection后,对PoolState进行源码解析。
复制代码
public class PoolState { // 连接池状态信息
protected PooledDataSource dataSource; // 此状态信息关联的数据源
protected final List<PooledConnection> idleConnections = new ArrayList<PooledConnection>(); // 空闲连接列表
protected final List<PooledConnection> activeConnections = new ArrayList<PooledConnection>(); // 活跃连接列表
protected long requestCount = 0; // 请求数
protected long accumulatedRequestTime = 0; // 累加请求所用时间
protected long accumulatedCheckoutTime = 0; // 累加占用连接所用时间
protected long claimedOverdueConnectionCount = 0; // 连接超时的数量
protected long accumulatedCheckoutTimeOfOverdueConnections = 0; // 累加超时的连接超时的时间
protected long accumulatedWaitTime = 0; // 累加等待获取连接所用时间
protected long hadToWaitCount = 0; // 等待获取连接的线程数
protected long badConnectionCount = 0; // 失效的连接数
复制代码
PoolState是对DataSource的状态管理类,主要包括如累计连接超时时间,失效连接的获取等一些状态信息的管理。除了包括一些数据库连接的记录信息外,内部还维护了两个数据库连接的列表idleConnections,activeConnections.。分别用来存放空闲的数据库连接列表,活跃的数据库连接列表,针对此两个列表的操作,下文在分析PooledDataSource时会进行详细介绍。
对PoolConnection和PoolState分析结束后,具体分析PoolDataSource源码。
复制代码
public class PooledDataSource implements DataSource {
private static final Log log = LogFactory.getLog(PooledDataSource.class);
private final PoolState state = new PoolState(this); // 维护数据源的状态
private final UnpooledDataSource dataSource; // 使用UnpooledDataSource来建立真正的连接
// OPTIONAL CONFIGURATION FIELDS
protected int poolMaximumActiveConnections = 10; // 最大活跃的连接数
protected int poolMaximumIdleConnections = 5; // 最大空闲的连接数
protected int poolMaximumCheckoutTime = 20000; // 最大checkout时间(checkOutTime指的是从数据源中获取连接到归还连接的时间)
protected int poolTimeToWait = 20000; // 最大等待时间
protected String poolPingQuery = "NO PING QUERY SET"; // 使用该语句来验证该连接是否有效
protected boolean poolPingEnabled = false;
protected int poolPingConnectionsNotUsedFor = 0;
private int expectedConnectionTypeCode; // hashcode
深圳网站建设www.sz886.com