UnpooledDataSource
从名称上即可知道,该种数据源不具有池化特性。该种数据源每次会返回一个新的数据库连接,而非复用旧的连接。由于UnpooledDataSource无需提供连接池功能,因此它的实现非常简单。核心的方法有三个,分别如下:
- initializeDriver - 初始化数据库驱动
- doGetConnection - 获取数据连接
- configureConnection - 配置数据库连接
初始化数据库驱动
使用 JDBC 访问数据库时的情景,在执行SQL之前,通常都是先获取数据库连接。一般步骤都是加载数据库驱动,然后通过 DriverManager 获取数据库连接。UnpooledDataSource 也是使用 JDBC 访问数据库的,因此它获取数据库连接的过程也大致如此,只不过会稍有不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| // -☆- UnpooledDataSource private synchronized void initializeDriver() throws SQLException { // 检测缓存中是否包含了与 driver 对应的驱动实例 if (!registeredDrivers.containsKey(driver)) { Class<?> driverType; try { // 加载驱动类型 if (driverClassLoader != null) { // 使用 driverClassLoader 加载驱动 driverType = Class.forName(driver, true, driverClassLoader); } else { // 通过其他 ClassLoader 加载驱动 driverType = Resources.classForName(driver); } // 通过反射创建驱动实例 Driver driverInstance = (Driver) driverType.newInstance(); // 注册驱动,注意这里是将 Driver 代理类 DriverProxy 对象注册到 // 而非 Driver 对象本身。DriverProxy 中并没什么特别的逻辑,就不分析。 DriverManager.registerDriver(new DriverProxy(driverInstance)); // 缓存驱动类名和实例 registeredDrivers.put(driver, driverInstance); } catch (Exception e) { throw new SQLException("……"); } } }
|
如上,initializeDriver 方法主要包含三步操作,分别如下:
- 加载驱动
- 通过反射创建驱动实例
- 注册驱动实例
上面代码中出现了缓存相关的逻辑,这个是用于避免重复注册驱动。因为initializeDriver 方法并不是在 UnpooledDataSource初始化时被调用的,而是在获取数据库连接时被调用的。因此这里需要做个检测,避免每次获取数据库连接时都重新注册驱动。
获取数据库连接
通过 DriverManager 的接口方法获取数据库连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| // -☆- UnpooledDataSource public Connection getConnection() throws SQLException { return doGetConnection(username, password); }
private Connection doGetConnection(String username, String password) throws SQLException { Properties props = new Properties(); if (driverProperties != null) { props.putAll(driverProperties); } if (username != null) { // 存储 user 配置 props.setProperty("user", username); } if (password != null) { // 存储 password 配置 props.setProperty("password", password); } // 调用重载方法 return doGetConnection(props); }
private Connection doGetConnection(Properties properties) throws SQLException { // 初始化驱动 initializeDriver(); // 获取连接 Connection connection = DriverManager.getConnection(url, properties); // 配置连接,包括自动ᨀ交以及事务等级 configureConnection(connection); return connection; }
private void configureConnection(Connection conn) throws SQLException { if (autoCommit != null && autoCommit != conn.getAutoCommit()) { // 设置自动提交 conn.setAutoCommit(autoCommit); } if (defaultTransactionIsolationLevel != null) { // 设置事务隔离级别 conn.setTransactionIsolation(defaultTransactionIsolationLevel); } }
|
上面方法将一些配置信息放入到 Properties 对象中,然后将数据库连接和Properties 对象传给 DriverManager 的 getConnection 方法即可获取到数据库连接