kk_cockroach

           

          2015年4月13日

          使用Proxy模擬一個最簡單的數(shù)據(jù)庫Connection池和PrepareStatment池

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

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

          import java.sql.Connection;

          public interface ConnectionPool
          {
          Connection getConnection();
          boolean releaseConnection(Connection proxy, Connection connection);
          }
          2. 連接池實現(xiàn)類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();
          }
          }

          代碼功能很簡單,但麻雀雖小五臟俱全。
          當(dāng)Connection容量設(shè)置為1時候,執(zhí)行結(jié)果:
          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 **
          從結(jié)果可以表明沒有使用緩存,每次都是取最新的記錄

          當(dāng)Connection容量設(shè)置為2時候,執(zhí)行結(jié)果:
          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 **
          從結(jié)果可以表明使用了緩存,第二次使用的是第一次緩存記錄

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

          僅列出標(biāo)題  

          導(dǎo)航

          統(tǒng)計

          留言簿

          隨筆檔案

          文章分類

          搜索

          最新評論

          主站蜘蛛池模板: 许昌县| 武川县| 合肥市| 六枝特区| 孟村| 通化县| 固安县| 望都县| 阿城市| 府谷县| 鹤岗市| 北安市| 梧州市| 万州区| 洛扎县| 繁峙县| 康保县| 都安| 吕梁市| 高尔夫| 华阴市| 溆浦县| 桐城市| 临漳县| 大港区| 佛坪县| 蒲城县| 信宜市| 嘉定区| 新疆| 金沙县| 咸宁市| 伊春市| 平武县| 香港| 盈江县| 扶余县| 湖南省| 道真| 财经| 临江市|