因为每次数据库连接的创建和销毁都比较耗时耗力。因此基本策略时候使用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); } } ); } }