kk_cockroach

           

          使用Proxy模擬一個最簡單的數據庫Connection池和PrepareStatment池

          今天在看夏欣老師的《深入淺出Hibernate》的時候,覺得老師在講數據庫連接池的時候的例子很不錯,使用Java動態代理實現對Connection攔截從而讓應用者使用連接池的時候不會因為手賤將Connection給關閉了,代碼如下:

          1. 連接池接口類ConnectionPool
          package com.snippnet.pool;

          import java.sql.Connection;

          public interface ConnectionPool
          {
          Connection getConnection();
          boolean releaseConnection(Connection proxy, Connection connection);
          }
          2. 連接池實現類DBConnectionPool
          package com.snippnet.pool;

          import java.sql.Connection;
          import java.sql.DriverManager;
          import java.sql.SQLException;
          import java.util.ArrayList;
          import java.util.List;

          import org.apache.commons.collections.CollectionUtils;

          public class DBConnectionPool implements ConnectionPool
          {
          private List<Connection> connections;
          private int size; //最大容量
          static {
          try
          {
          Class.forName("com.mysql.jdbc.Driver");
          } catch (ClassNotFoundException e)
          {
          e.printStackTrace();
          }
          }
          public DBConnectionPool(int size)
          {
          this.size = size;
          connections = new ArrayList<Connection>();
          }
          public synchronized Connection getConnection()
          {
          Connection connection = null;
          if (CollectionUtils.isEmpty(connections))
          {
          try
          {
          connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jira", "root", "root");
          ConnectionHandler handler = new ConnectionHandler(this, connection);
          // connection = (Connection)Proxy.newProxyInstance(this.getClass().getClassLoader(), connection.getClass().getInterfaces(), (InvocationHandler) handler);
          connection = handler.bind(connection);
          // connections.add(connection);
          } catch (SQLException e)
          {
          e.printStackTrace();
          }
          } else
          {
          connection = connections.get(connections.size() - 1);
          connections.remove(connections.size() - 1);
          }
          return connection;
          }
          public synchronized boolean releaseConnection(Connection proxy, Connection connection)
          {
          boolean bool = false;
          if (connections != null)
          {
          if (connections.size() < (this.size - 1))
          {
          connections.add(proxy);
          bool = true;
          } else
          {
          try
          {
          if (!connection.isClosed())
          {
          connection.close();
          }
          bool = true;
          } catch (SQLException e)
          {
          bool = false;
          }
          }
          }
          return bool;
          }
          }
          3. 攔截器類ConnectionHandler
          package com.snippnet.pool;

          import java.lang.reflect.InvocationHandler;
          import java.lang.reflect.Method;
          import java.lang.reflect.Proxy;
          import java.sql.Connection;
          import java.sql.PreparedStatement;
          import java.util.Collections;
          import java.util.HashMap;
          import java.util.Map;

          public class ConnectionHandler implements InvocationHandler
          {
          private ConnectionPool pool;
          private Connection connection;
          private Map<String, PreparedStatement> pstPool;

          public ConnectionHandler(ConnectionPool pool, Connection connection)
          {
          this.pool = pool;
          this.connection = connection;
          this.pstPool = Collections.synchronizedMap(new HashMap<String, PreparedStatement>());
          }

          public Connection bind(Connection connection)
          {
          this.connection = connection;
          return (Connection) Proxy.newProxyInstance(connection.getClass().getClassLoader()
          , new Class[]{Connection.class}
          , this);
          }

          @Override
          public Object invoke(Object proxy, Method method, Object[] args)
          throws Throwable
          {
          Object obj = null;
          if ("close".equals(method.getName()))
          {
          // 若為close方法
          obj = pool.releaseConnection((Connection)proxy, connection);
          else if ("prepareStatement".equals(method.getName()))
          {
          if (pstPool.containsKey((String)args[0]))
          {
          obj = pstPool.get((String)args[0]);
          } else
          {
          String sql = (String)args[0];
          obj = connection.prepareStatement(sql);
          PrepareStatementHandler handler = new PrepareStatementHandler();
          obj = handler.bind((PreparedStatement)obj);
          pstPool.put(sql, (PreparedStatement)obj);
          }
          }
          else
          {
          // 不為close方法
          obj = method.invoke(connection, args);
          }
          return obj;
          }

          }
          4. 測試類
          package com.snippnet.pool;

          import java.sql.Connection;
          import java.sql.PreparedStatement;

          public class DynamicConnectionPoolTest
          {
          public static void main(String[] args) throws Exception
          {
          ConnectionPool pool = new DBConnectionPool(2);
          Connection con = pool.getConnection();
          PreparedStatement pst = con.prepareStatement("SELECT id FROM cwd_group WHERE id = ?");
          System.out.println(con);
          System.out.println(pst);
          con.close();
          Connection con1 = pool.getConnection();
          System.out.println(con1);
          PreparedStatement pst2 = con1.prepareStatement("SELECT id FROM cwd_group WHERE id = ?");
          System.out.println(pst2);
          con.close();
          }
          }

          代碼功能很簡單,但麻雀雖小五臟俱全。
          當Connection容量設置為1時候,執行結果:
          com.mysql.jdbc.JDBC4Connection@6276e5
          com.mysql.jdbc.JDBC4PreparedStatement@edeea8: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **
          com.mysql.jdbc.JDBC4Connection@1d44ae9
          com.mysql.jdbc.JDBC4PreparedStatement@823618: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **
          從結果可以表明沒有使用緩存,每次都是取最新的記錄

          當Connection容量設置為2時候,執行結果:
          com.mysql.jdbc.JDBC4Connection@6276e5
          com.mysql.jdbc.JDBC4PreparedStatement@edeea8: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **
          com.mysql.jdbc.JDBC4Connection@6276e5
          com.mysql.jdbc.JDBC4PreparedStatement@edeea8: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **
          從結果可以表明使用了緩存,第二次使用的是第一次緩存記錄

          posted on 2015-04-13 23:33 編程小強 閱讀(277) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          留言簿

          隨筆檔案

          文章分類

          搜索

          最新評論

          主站蜘蛛池模板: 班玛县| 喀什市| 通许县| 澄江县| 济宁市| 新昌县| 蕉岭县| 宁海县| 隆安县| 波密县| 印江| 海晏县| 辛集市| 彭阳县| 敦煌市| 屏东县| 石屏县| 桂平市| 东安县| 都昌县| 鄂尔多斯市| 思茅市| 将乐县| 新晃| 无为县| 佛学| 会昌县| 汉中市| 和平区| 枝江市| 古交市| 象山县| 城固县| 高阳县| 溧阳市| 益阳市| 玛曲县| 汉阴县| 申扎县| 正定县| 乳源|