国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池

2019-11-18 12:08:50
字體:
供稿:網(wǎng)友

  劉冬
  珠海市創(chuàng)我科技發(fā)展有限公司軟件工程師
  
  數(shù)據(jù)庫連接池在編寫應用服務是經(jīng)常需要用到的模塊,太過頻繁的連接數(shù)據(jù)庫對服務性能來講是一個瓶頸,使用緩沖池技術可以來消除這個瓶頸。我們可以在互聯(lián)網(wǎng)上找到很多關于數(shù)據(jù)庫連接池的源程序,但是都發(fā)現(xiàn)這樣一個共同的問題:這些連接池的實現(xiàn)方法都不同程度地增加了與使用者之間的耦合度。很多的連接池都要求用戶通過其規(guī)定的方法獲取數(shù)據(jù)庫的連接,這一點我們可以理解,究竟目前所有的應用服務器取數(shù)據(jù)庫連接的方式都是這種方式實現(xiàn)的。但是另外一個共同的問題是,它們同時不答應使用者顯式的調(diào)用Connection.close()方法,而需要用其規(guī)定的一個方法來關閉連接。這種做法有兩個缺點:
  
  第一:改變了用戶使用習慣,增加了用戶的使用難度。
  
  首先我們來看看一個正常的數(shù)據(jù)庫操作過程:
  
  int executeSQL(String sql) throws SQLException
  {
     Connection conn = getConnection();   //通過某種方式獲取數(shù)據(jù)庫連接
     PReparedStatement ps = null;
     int res = 0;
     try{
       ps = conn.prepareStatement(sql);
       res = ps.executeUpdate();
  }finally{
  try{
  ps.close();
  }catch(Exception e){}
  try{
     conn.close();//
  }catch(Exception e){}
  }
  return res;
  }
  
  使用者在用完數(shù)據(jù)庫連接后通常是直接調(diào)用連接的方法close來釋放數(shù)據(jù)庫資源,假如用我們前面提到的連接池的實現(xiàn)方法,那語句conn.close()將被某些特定的語句所替代。
  
  第二:使連接池無法對之中的所有連接進行獨占控制。
  
  由于連接池不答應用戶直接調(diào)用連接的close方法,一旦使用者在使用的過程中由于習慣問題直接關閉了數(shù)據(jù)庫連接,那么連接池將無法正常維護所有連接的狀態(tài),考慮連接池和應用由不同開發(fā)人員實現(xiàn)時這種問題更輕易出現(xiàn)。
  
  綜合上面提到的兩個問題,我們來討論一下如何解決這兩個要命的問題。
  
  首先我們先設身處地的考慮一下用戶是想怎么樣來使用這個數(shù)據(jù)庫連接池的。用戶可以通過特定的方法來獲取數(shù)據(jù)庫的連接,同時這個連接的類型應該是標準的java.sql.Connection。用戶在獲取到這個數(shù)據(jù)庫連接后可以對這個連接進行任意的操作,包括關閉連接等。
  
  通過對用戶使用的描述,怎樣可以接管Connection.close方法就成了我們這篇文章的主題。
  
  為了接管數(shù)據(jù)庫連接的close方法,我們應該有一種類似于鉤子的機制。例如在Windows編程中我們可以利用Hook API來實現(xiàn)對某個Windows API的接管。在JAVA中同樣也有這樣一個機制。JAVA提供了一個Proxy類和一個InvocationHandler,這兩個類都在java.lang.reflect包中。我們先來看看SUN公司提供的文檔是怎么描述這兩個類的。
  
  public interface InvocationHandler
  
  InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
  
  Each proxy instance has an associated invocation handler.
  When a method is invoked on a proxy instance,
  the method invocation is encoded and dispatched to the invoke method of its invocation handler.
  
   SUN的API文檔中關于Proxy的描述很多,這里就不羅列出來。通過文檔對接口InvocationHandler的描述我們可以看到當調(diào)用一個Proxy實例的方法時會觸發(fā)Invocationhanlder的invoke方法。從JAVA的文檔中我們也同時了解到這種動態(tài)代理機制只能接管接口的方法,而對一般的類無效,考慮到java.sql.Connection本身也是一個接口由此就找到了解決如何接管close方法的出路。
  
  首先,我們先定義一個數(shù)據(jù)庫連接池參數(shù)的類,定義了數(shù)據(jù)庫的JDBC驅(qū)動程序類名,連接的URL以及用戶名口令等等一些信息,該類是用于初始化連接池的參數(shù),具體定義如下:
  
  
  public class ConnectionParam implements Serializable
  {
     private String driver;          //數(shù)據(jù)庫驅(qū)動程序
     private String url;             //數(shù)據(jù)連接的URL
     private String user;             //數(shù)據(jù)庫用戶名
     private String passWord;          //數(shù)據(jù)庫密碼
     private int minConnection = 0;     //初始化連接數(shù)
     private int maxConnection = 50;     //最大連接數(shù)
     private long timeoutValue = 600000;//連接的最大空閑時間
     private long waitTime = 30000;     //取連接的時候假如沒有可用連接最大的等待時間
  
   其次是連接池的工廠類ConnectionFactory,通過該類來將一個連接池對象與一個名稱對應起來,使用者通過該名稱就可以獲取指定的連接池對象,具體代碼如下:
  
  
  /**
   * 連接池類廠,該類常用來保存多個數(shù)據(jù)源名稱合數(shù)據(jù)庫連接池對應的哈希
   * @author liusoft
   */
  public class ConnectionFactory
  {
     //該哈希表用來保存數(shù)據(jù)源名和連接池對象的關系表
     static Hashtable connectionPools = null;
     static{
       connectionPools = new Hashtable(2,0.75F);
     }
     /**
     * 從連接池工廠中獲取指定名稱對應的連接池對象
     * @param dataSource   連接池對象對應的名稱
     * @return DataSource   返回名稱對應的連接池對象
     * @throws NameNotFoundException   無法找到指定的連接池
     */
     public static DataSource lookup(String dataSource)
       throws NameNotFoundException
     {
       Object ds = null;
       ds = connectionPools.get(dataSource);
       if(ds == null !(ds instanceof DataSource))
          throw new NameNotFoundException(dataSource);
       return (DataSource)ds;
     }
  
     /**
     * 將指定的名字和數(shù)據(jù)庫連接配置綁定在一起并初始化數(shù)據(jù)庫連接池
     * @param name     對應連接池的名稱
     * @param param   連接池的配置參數(shù),具體請見類ConnectionParam
     * @return DataSource   假如綁定成功后返回連接池對象
     * @throws NameAlreadyBoundException   一定名字name已經(jīng)綁定則拋出該異常
     * @throws ClassNotFoundException     無法找到連接池的配置中的驅(qū)動程序類
     * @throws IllegalaccessException     連接池配置中的驅(qū)動程序類有誤
     * @throws InstantiationException     無法實例化驅(qū)動程序類
     * @throws SQLException          無法正常連接指定的數(shù)據(jù)庫
     */
     public static DataSource bind(String name, ConnectionParam param)
       throws NameAlreadyBoundException,ClassNotFoundException,
            IllegalAccessException,InstantiationException,SQLException
     {
       DataSourceImpl source = null;
       try{
          lookup(name);
          throw new NameAlreadyBoundException(name);
       }catch(NameNotFoundException e){
          source = new DataSourceImpl(param);
          source.initConnection();
          connectionPools.put(name, source);
       }
       return source;
     }
     /**
     * 重新綁定數(shù)據(jù)庫連接池
     * @param name     對應連接池的名稱
     * @param param   連接池的配置參數(shù),具體請見類ConnectionParam
     * @return DataSource   假如綁定成功后返回連接池對象
     * @throws NameAlreadyBoundException   一定名字name已經(jīng)綁定則拋出該異常
     * @throws ClassNotFoundException     無法找到連接池的配置中的驅(qū)動程序類
     * @throws IllegalAccessException     連接池配置中的驅(qū)動程序類有誤
     * @throws InstantiationException     無法實例化驅(qū)動程序類
     * @throws SQLException          無法正常連接指定的數(shù)據(jù)庫
     */
     public static DataSource rebind(String name, ConnectionParam param)
       throws NameAlreadyBoundException,ClassNotFoundException,
            IllegalAccessException,InstantiationException,SQLException
     {
       try{
          unbind(name);
       }catch(Exception e){}
       return bind(name, param);
     }
     /**
     * 刪除一個數(shù)據(jù)庫連接池對象
     * @param name
     * @throws NameNotFoundException
     */
     public static void unbind(String name) throws

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 江陵县| 错那县| 峨眉山市| 嘉禾县| 安达市| 米泉市| 汤阴县| 秦安县| 乌拉特中旗| 文登市| 鄂州市| 长沙县| 镇巴县| 青神县| 永州市| 东海县| 邢台市| 张家川| 武冈市| 西吉县| 田林县| 调兵山市| 德令哈市| 沂源县| 五华县| 江达县| 科技| 阿拉善左旗| 惠来县| 花垣县| 江永县| 湖口县| 荣成市| 东辽县| 高雄县| 兴仁县| 聊城市| 平利县| 白山市| 昌乐县| 苍溪县|