因为每次数据库连接的创建和销毁都比较耗时耗力。因此基本策略时候使用JDBC连接池来管理所有的连接。
一般connection pool 只是一个 LinkedList 即可。
比如我们自己写一个javax.sql.DataSource的实现类,类中有一个private变量: LinkedList<Connection> pool = new LinkedList<Connection>();
可以写一个静态代码快来初始化pool变量: 如新建10个Conncetion。
- private static LinkedList<Connection> pool = new LinkedList<Connection>();
- static{
- //初始化DriverManager
- //......
- for(int i=0; i<10; i++){
- Connection conn = DriverManager.getConnection(url, username,password);
- pool.add(conn);
- }
- }
当客户端调用dataSource.getConnection() 时并不新建Connection, 而是从pool中取出一个Connection实例传给客户端。
但是,当客户端调用connection.close(); 函数时, 我们应实现将次connection还回pool中,而不是真的关闭connection。但是connection.close() 函数本是被Driver实现的(mysql 的话是mysql的driver, oracle的话是oracle的driver。我们是无法改变driver内部的实现的。解决方案只能是外部对close() 方法的重写或扩展。
解决方案:
(一). 装饰模式
被改写类: com.mysql.jdbc.Connection
编写一个类CustomedConnection 实现与com.mysql.jdbc.Connection 相同的接口(java.sql.Conneciton)
- public class CustomedConnection implements java.sql.Connection{
- private Connection sqlConnection ;
- private LinkedList<Connection> pool;
- public CustomedConnection(Connection sqlConnection, LinkedList<Connection> pool){
- this.sqlConnection = sqlConnection;
- this.pool = pool;
- }
- public void close(){
- this.pool.add(sqlConnection);
- }
- // ......
- //java.sql.Connection 的其他方法的实现都直接调用sqlConnection的实现即可。除了close() 方法。
- // ......
- }
DataSource 的实现中:
- public synchronized Connection getConnection() throws SQLException{
- if(pool.size()>0){
- Connection conn = pool.remove();//从池中拿出一个connection
- CustomedConnection customedConnection = new CustomedConnection(conn, pool);
- return customedConnection;
- }
- else{
- throw new RuntimeException(“sorry, server busy”);
- }
- }
(二). 适配器模式
- public class ConnectionAdaptor implements Connection{
- private Connection conn;
- public ConnectionAdaptor(Connection conn){
- this.conn=conn;
- }
- //重写所有Connection的方法:都直接调用conn的响应方法即可。
- //......
- }
- //接下来写一个CustomedConnection 继承此适配器:
- public class CustomedConnection extends ConnectionAdaptor {
- private LinkedList<Connection> pool ;
- public CustomedConnection(Connection conn, LinkedList<Connection> pool){
- super(conn);
- this.pool = pool;
- }
- //重写close() 方法即可
- //......
- }
(三).动态代理
在实现DataSource的getConnection()方法里,拦截Connection的所有方法,如果方法名为close, 则改变其原本逻辑:
- public synchronized Connection getConnection(){
- if(pool.size()>0){
- final Connection conn = pool.remove();
- return Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler(){
- @Override
- public Object invoke(Object proxy, Method method, Object[] args){
- if("close".equals(methode))
- return pool.add(conn);
- else
- return method.invoke(proxy, args);
- }
- }
- );
- }
- }