六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

使用JAVA中的動態代理完成數據庫連接池

[摘要]數據庫連接池在編寫應用服務是經常需要用到的模塊,太過頻繁的連接數據庫對服務性能來講是一個瓶頸,使用緩沖池技術可以來消除這個瓶頸。我們可以在互聯網上找到很多關于數據庫連接池的源程序,但是都發現這樣一個共同的問題:這些連接池的實現方法都不同程度地增加了與使用者之間的耦合度。很多的連接池都要求用戶通過其...
數據庫連接池在編寫應用服務是經常需要用到的模塊,太過頻繁的連接數據庫對服務性能來講是一個瓶頸,使用緩沖池技術可以來消除這個瓶頸。我們可以在互聯網上找到很多關于數據庫連接池的源程序,但是都發現這樣一個共同的問題:這些連接池的實現方法都不同程度地增加了與使用者之間的耦合度。很多的連接池都要求用戶通過其規定的方法獲取數據庫的連接,這一點我們可以理解,畢竟目前所有的應用服務器取數據庫連接的方式都是這種方式實現的。但是另外一個共同的問題是,它們同時不允許使用者顯式的調用Connection.close()方法,而需要用其規定的一個方法來關閉連接。這種做法有兩個缺點:

  第一:改變了用戶使用習慣,增加了用戶的使用難度。

  首先我們來看看一個正常的數據庫操作過程:

  int executeSQL(String sql) throws SQLException
  {
   Connection conn = getConnection(); //通過某種方式獲取數據庫連接
   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;
  }

  使用者在用完數據庫連接后通常是直接調用連接的方法close來釋放數據庫資源,如果用我們前面提到的連接池的實現方法,那語句conn.close()將被某些特定的語句所替代。

  第二:使連接池無法對之中的所有連接進行獨占控制。由于連接池不允許用戶直接調用連接的close方法,一旦使用者在使用的過程中由于習慣問題直接關閉了數據庫連接,那么連接池將無法正常維護所有連接的狀態,考慮連接池和應用由不同開發人員實現時這種問題更容易出現。

  綜合上面提到的兩個問題,我們來討論一下如何解決這兩個要命的問題。

  首先我們先設身處地的考慮一下用戶是想怎么樣來使用這個數據庫連接池的。用戶可以通過特定的方法來獲取數據庫的連接,同時這個連接的類型應該是標準的java.sql.Connection。用戶在獲取到這個數據庫連接后可以對這個連接進行任意的操作,包括關閉連接等。

  通過對用戶使用的描述,怎樣可以接管Connection.close方法就成了我們這篇文章的主題。

  為了接管數據庫連接的close方法,我們應該有一種類似于鉤子的機制。例如在Windows編程中我們可以利用Hook API來實現對某個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的描述我們可以看到當調用一個Proxy實例的方法時會觸發Invocationhanlder的invoke方法。從JAVA的文檔中我們也同時了解到這種動態代理機制只能接管接口的方法,而對一般的類無效,考慮到java.sql.Connection本身也是一個接口由此就找到了解決如何接管close方法的出路。

  首先,我們先定義一個數據庫連接池參數的類,定義了數據庫的JDBC驅動程序類名,連接的URL以及用戶名口令等等一些信息,該類是用于初始化連接池的參數,具體定義如下:

  public class ConnectionParam implements Serializable
  {
   private String driver; //數據庫驅動程序
   private String url; //數據連接的URL
   private String user; //數據庫用戶名
   private String password; //數據庫密碼
   private int minConnection = 0; //初始化連接數
   private int maxConnection = 50; //最大連接數
   private long timeoutValue = 600000;//連接的最大空閑時間
   private long waitTime = 30000; //取連接的時候如果沒有可用連接最大的等待時間

  其次是連接池的工廠類ConnectionFactory,通過該類來將一個連接池對象與一個名稱對應起來,使用者通過該名稱就可以獲取指定的連接池對象,具體代碼如下:

  /**
   * 連接池類廠,該類常用來保存多個數據源名稱合數據庫連接池對應的哈希
   * @author liusoft
   */
  public class ConnectionFactory
  {
   //該哈希表用來保存數據源名和連接池對象的關系表
   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;
   }

   /**
   * 將指定的名字和數據庫連接配置綁定在一起并初始化數據庫連接池
   * @param name 對應連接池的名稱
   * @param param 連接池的配置參數,具體請見類ConnectionParam
   * @return DataSource 如果綁定成功后返回連接池對象
   * @throws NameAlreadyBoundException 一定名字name已經綁定則拋出該異常
   * @throws ClassNotFoundException 無法找到連接池的配置中的驅動程序類
   * @throws IllegalAccessException 連接池配置中的驅動程序類有誤
   * @throws InstantiationException 無法實例化驅動程序類
   * @throws SQLException 無法正常連接指定的數據庫
   */
   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;
   }
   /**
   * 重新綁定數據庫連接池
   * @param name 對應連接池的名稱
   * @param param 連接池的配置參數,具體請見類ConnectionParam
   * @return DataSource 如果綁定成功后返回連接池對象
   * @throws NameAlreadyBoundException 一定名字name已經綁定則拋出該異常
   * @throws ClassNotFoundException 無法找到連接池的配置中的驅動程序類
   * @throws IllegalAccessException 連接池配置中的驅動程序類有誤
   * @throws InstantiationException 無法實例化驅動程序類
   * @throws SQLException 無法正常連接指定的數據庫
   */
   public static DataSource rebind(String name, ConnectionParam param)
   throws NameAlreadyBoundException,ClassNotFoundException,
   IllegalAccessException,InstantiationException,SQLException
   {
   try{
   unbind(name);
   }catch(Exception e){}
   return bind(name, param);
   }
   /**
   * 刪除一個數據庫連接池對象
   * @param name
   * @throws NameNotFoundException
   */
   public static void unbind(String name) throws NameNotFoundException
   {
   DataSource dataSource = lookup(name);
   if(dataSource instanceof DataSourceImpl){
   DataSourceImpl dsi = (DataSourceImpl)dataSource;
   try{
   dsi.stop();
   dsi.close();
   }catch(Exception e){
   }finally{
   dsi = null;
   }
   }
   connectionPools.remove(name);
   }
  
  }

  ConnectionFactory主要提供了用戶將將連接池綁定到一個具體的名稱上以及取消綁定的操作。使用者只需要關心這兩個類即可使用數據庫連接池的功能。下面我們給出一段如何使用連接池的代碼:

   String name = "pool";
   String driver = " sun.jdbc.odbc.JdbcOdbcDriver ";
   String url = "jdbc:odbc:datasource";
   ConnectionParam param = new ConnectionParam(driver,url,null,null);
   param.setMinConnection(1);
   param.setMaxConnection(5);
   param.setTimeoutValue(20000);
   ConnectionFactory.bind(name, param);
   System.out.println("bind datasource ok.");
   //以上代碼是用來登記一個連接池對象,該操作可以在程序初始化只做一次即可
   //以下開始就是使用者真正需要寫的代碼
   DataSource ds = ConnectionFactory.lookup(name);
   try{
   for(int i=0;i<10;i++){
   Connection conn = ds.getConnection();
   try{
   testSQL(conn, sql);
   }finally{
   try{
   conn.close();
   }catch(Exception e){}
   }
   }
   }catch(Exception e){
   e.printStackTrace();
   }finally{
   ConnectionFactory.unbind(name);
   System.out.println("unbind datasource ok.");
   System.exit(0);
   }



主站蜘蛛池模板: 欧美一级性生活视频 | 青青精品| 又粗又黄又猛又爽大片app | 伊人日韩 | 午夜影视在线 | 香蕉网站狼人久久五月亭亭 | 三级黄色在线播放 | 亚洲精品乱码久久久久久 | 欧美一区二区亚洲 | 伊人中文字幕在线 | 亚洲精品第1页 | 四虎中文 | 四虎永久在线精品2022 | 视频午夜 | 午夜视频国语 | 天天天狠天天透天天制色 | 青草福利 | 午夜激情视频专区在线观看网站大全 | 亚洲欧美日韩综合久久久久 | 午夜在线播放免费高清观看 | 天天骑天天干 | 色天天综合久久久久综合片 | 亚洲精品国产v片在线观看 亚洲精品高清在线观看 | 婷婷丁香综合网 | 青青在线观看视频 | 日本在线观看一区二区三区 | 青娱乐在线视频观看 | 欧美一级特黄乱妇高清视频 | 深夜视频免费 | 欧美在线资源 | 视频二区欧美 | 日韩a一级欧美一级在线播放 | 天天躁夜夜躁狠狠躁躁88 | 中文字幕国产专区 | 日韩精品小视频 | 亚洲第一欧美 | 亚洲视频免费在线观看 | 日韩一级在线视频 | 伊人手机在线观看 | 四虎成人影院网址 | 天堂婷婷|