如何实现简易版的数据库连接池
1、前言
JDBC数据库的连接释放是很浪费资源的,如果每次操作数据库都新建连接显然是不符合业务要求的,在实际项目中我们常用的连接池有C3P0、DBCP等。那我们如何实际实现一个简易版的数据库连接池呢,核心思想就是使用动态代理来完成获取连接、释放。如是需要自己实现数据库连接池则需要实现DataSource接口,重写getConnection()方法。在数据库连接池中最重要的环节释放连接的时候,我们不是真正的释放连接,而是把连接返回到连接池中。这里讲的池也就是一个集合,我们用LinkedList来保存连接。
2、代码实现
public class JdbcPool implements DataSource {
//存放数据可的连接
private static LinkedList<Connection> listConnections = new LinkedList<>();
static {
InputStream in = JdbcPool.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop = new Properties();
try {
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
int jdbcPoolInitSize = Integer.parseInt(prop.getProperty("jdbcPoolInitSize"));
Class.forName(driver);
for (int i = 0; i < jdbcPoolInitSize; i++) {
Connection conn = DriverManager.getConnection(url, username, password);
listConnections.add(conn);
}
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
@Override
public synchronized Connection getConnection() {
if (listConnections.size() > 0) {
Connection connection = listConnections.removeFirst();
System.out.println("listConnections数据库连接池大小是" + listConnections.size());
return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(), connection.getClass().getInterfaces(), (proxy, method, args) -> {
if (!"close".equals(method.getName())) {
return method.invoke(connection, args);
} else {
listConnections.add(connection);
System.out.println(connection + "被还给listConnections数据库连接池了!!");
System.out.println("listConnections数据库连接池大小为" + listConnections.size());
return null;
}
});
} else {
System.out.println("数据库繁忙!");
}
return null;
}
....
从获取链接的时候我们可以看到,我们获取的Connection是代理对象,当我们释放连接的时候是把连接返回到List中的。
3、配置文件
db.properties 放在calsspath下
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=false
username=root
password=123456
jdbcPoolInitSize=10