1. 程式人生 > >JDBC-連線池之裝飾者和動態代理

JDBC-連線池之裝飾者和動態代理

前言

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;
        }
    }
}

總結

通過裝飾者模式和動態代理都優化了連線池操作,但是相比之下,還是動態代理更好,只需要根據需要來實現相關的方法,不需要重寫介面中所有的方法。通過反射來判斷當下執行的方法,動態的去選擇執行者。