JDBC-連線池之裝飾者和動態代理
阿新 • • 發佈:2018-12-13
前言
JDBC連線池的存在,解決了資料庫連線和釋放資源的效能問題,通過在程式初始化的時候建立一定數量的連線,通過集合儲存,每當需要進行資料庫操作的時候,在連線池中拿,使用完畢後,不是釋放資源而是在將拿出的連線物件放入集合中,這樣就提高了效能。
通過裝飾者模式來定義連線池
定義Connection實現
public class MyConnection implements Connection {
private Connection connection;
private LinkedList<Connection> linkedList;
public MyConnection(Connection connection, LinkedList<Connection> linkedList) {
this.connection = connection;
this .linkedList = linkedList;
}
@Override
public Statement createStatement() throws SQLException {
return connection.createStatement();
}
@Override
public void close() throws SQLException {
System.out.println("=========");
//將回收的Connection例項加進集合中
linkedList.addLast(connection);
}
......
......
}
定義DataSource實現的實現
/**
* Created by yzz on 2017/8/27.
* mail:[email protected]
*/
public class ConnectionPool_1 implements DataSource {
private static LinkedList<Connection> linkedList = new LinkedList<>();
static {
//類載入時建立一定數量的連線
initPool();
}
public static void initPool(){
for (int i = 0; i <5 ; i++) {
Connection connection = JDBCUtils.getConnection();
//將Connection物件進行裝飾
MyConnection conn = new MyConnection(connection,linkedList);
//將裝飾著的例項加入到集合中
linkedList.addFirst(conn);
}
}
@Override
public Connection getConnection() throws SQLException {
if (linkedList.size()==0){
initPool();
}
//訪問一個連線,集合就要移除該連線
return linkedList.removeFirst();
}
public static void close(Connection connection){
if (connection==null)return;
try {
//呼叫的close方法是裝飾過後的方法
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
......
......
}
通過動態代理來定義連線池
定義Connection實現
只需要實現close方法即可,只要當呼叫close方法時,才會去代理目標,其他方法代理不做任何事,還是交給目標Connection執行。
public class ConnectionProxy implements Connection{
private Connection connection;
private LinkedList<Connection> linkedList;
public ConnectionProxy(Connection connection, LinkedList<Connection> linkedList) {
this.connection = connection;
this.linkedList = linkedList;
}
@Override
public void close() throws SQLException {
System.out.println("=====================");
linkedList.addLast(connection);
}
......
......
}
動態代理,動態的去選擇執行物件
/**
* Created by yzz on 2017/8/27.
* mail:[email protected]
* 1.傳遞一個目標物件和一個代理實現
* 2.當呼叫close方法時由代理物件執行,否則由目標物件執行
* 3.在invoke()的返回值就是方法呼叫的返回值,使用者不能自己想當然,必須要嚴謹
*/
public class Connectionutils {
public static Connection getConn(Connection connection,Connection proxyConn){
Connection c = null;
try {
c = (Connection) Proxy.newProxyInstance(
connection.getClass().getClassLoader(),
new Class[]{Connection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass());
if ("close".equals(method.getName())){
return method.invoke(proxyConn,args);
}else {
return method.invoke(connection,args);
}
}
}
);
}catch (Exception e){
e.printStackTrace();
}finally {
return c;
}
}
}
總結
通過裝飾者模式和動態代理都優化了連線池操作,但是相比之下,還是動態代理更好,只需要根據需要來實現相關的方法,不需要重寫介面中所有的方法。通過反射來判斷當下執行的方法,動態的去選擇執行者。