JDBC-连接池之装饰者和动态代理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22271479/article/details/77621836

前言

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

总结

通过装饰者模式和动态代理都优化了连接池操作,但是相比之下,还是动态代理更好,只需要根据需要来实现相关的方法,不需要重写接口中所有的方法。通过反射来判断当下执行的方法,动态的去选择执行者。

猜你喜欢

转载自blog.csdn.net/qq_22271479/article/details/77621836