如何基于dbcp2重写DataSource以动态使用自定义数据库连接类
使用DBCP2实现动态选择自定义连接类的DataSource方案
核心思路
DBCP2的BasicDataSource是默认实现,我们可以通过继承它并自定义ConnectionFactory,在获取连接时根据输入参数动态切换对应的自定义连接类实例,核心是把不同连接类的创建逻辑做映射,按需调用。
步骤1:实现动态ConnectionFactory
DBCP2依赖ConnectionFactory创建连接,我们写一个动态实现类,通过标识映射不同连接的创建逻辑:
import org.apache.commons.dbcp2.ConnectionFactory; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import java.util.function.Supplier; public class DynamicConnectionFactory implements ConnectionFactory { // 存储连接类型与对应创建器的映射 private final Map<String, Supplier<Connection>> connectionSuppliers; // 默认连接创建逻辑 private final Supplier<Connection> defaultSupplier; public DynamicConnectionFactory(Map<String, Supplier<Connection>> suppliers, Supplier<Connection> defaultSupplier) { this.connectionSuppliers = suppliers; this.defaultSupplier = defaultSupplier; } // 带类型参数的连接创建方法 public Connection createConnection(String connectionType) throws SQLException { Supplier<Connection> supplier = connectionSuppliers.getOrDefault(connectionType, defaultSupplier); try { return supplier.get(); } catch (Exception e) { throw new SQLException("创建[" + connectionType + "]类型连接失败", e); } } // 实现父接口无参方法,返回默认连接 @Override public Connection createConnection() throws SQLException { return createConnection(null); } }
步骤2:扩展BasicDataSource,新增动态获取连接方法
继承BasicDataSource,替换默认的ConnectionFactory为我们的动态实现,并新增带参数的连接获取方法:
import org.apache.commons.dbcp2.BasicDataSource; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; public class DynamicDataSource extends BasicDataSource { private DynamicConnectionFactory dynamicConnectionFactory; @Override protected void createConnectionFactory() throws SQLException { // 初始化自定义连接类的创建逻辑映射 Map<String, Supplier<Connection>> suppliers = Map.of( "type1", () -> new MyConnectionClass1(getUrl(), getUsername(), getPassword()), "type2", () -> new MyConnectionClass2(getUrl(), getUsername(), getPassword()) ); // 默认使用type1类型连接 dynamicConnectionFactory = new DynamicConnectionFactory(suppliers, suppliers.get("type1")); setConnectionFactory(dynamicConnectionFactory); } // 新增根据类型获取连接的方法 public Connection getConnection(String connectionType) throws SQLException { if (dynamicConnectionFactory == null) { createConnectionFactory(); } return dynamicConnectionFactory.createConnection(connectionType); } }
步骤3:业务代码中动态调用
直接传入连接类型标识,获取对应自定义连接:
public class BusinessDemo { public static void main(String[] args) throws SQLException { DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/test_db"); dataSource.setUsername("root"); dataSource.setPassword("your_password"); // 获取MyConnectionClass1类型连接 Connection conn1 = dataSource.getConnection("type1"); // 获取MyConnectionClass2类型连接 Connection conn2 = dataSource.getConnection("type2"); } }
关键注意事项
- 所有自定义连接类必须完整实现
java.sql.Connection接口,否则DBCP2的连接池管理(如连接状态跟踪、回收机制)会失效。 - 如果自定义连接是对原生JDBC连接的包装,要确保
close()等核心方法正确委托给原生连接,避免连接泄漏。 - 可根据需求扩展映射逻辑,比如从配置文件加载连接类映射,或者结合请求上下文自动匹配连接类型。
内容的提问来源于stack exchange,提问作者Vishva N
相关产品推荐
相关产品推荐

