久草成人在线视频,欧美激情视频网,级别免费毛片在线看,中文字幕色婷婷在线视频,亚洲天堂成人在线,久久亚洲婷,日本黄色网址在线免费

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

上傳人:wuyo****995 文檔編號:108181759 上傳時間:2022-06-15 格式:DOC 頁數(shù):10 大?。?8.51KB
收藏 版權(quán)申訴 舉報 下載
使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池_第1頁
第1頁 / 共10頁
使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池_第2頁
第2頁 / 共10頁
使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池_第3頁
第3頁 / 共10頁

下載文檔到電腦,查找使用更方便

9.9 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池》由會員分享,可在線閱讀,更多相關(guān)《使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池(10頁珍藏版)》請在裝配圖網(wǎng)上搜索。

1、 使用JAVA中的動態(tài)代理實現(xiàn)數(shù)據(jù)庫連接池 數(shù)據(jù)庫連接池在編寫應(yīng)用服務(wù)是經(jīng)常需要用到的模塊,太過頻繁的連接數(shù)據(jù)庫對服務(wù)性能來講是一個瓶頸,使用緩沖池技術(shù)可以來消除這個瓶頸。我們可以在互聯(lián)網(wǎng)上找到很多關(guān)于數(shù)據(jù)庫連接池的源程序,但是都發(fā)現(xiàn)這樣一個共同的問題:這些連接池的實現(xiàn)方法都不同程度地增加了與使用者之間的耦合度。很多的連接池都要求用戶通過其規(guī)定的方法獲取數(shù)據(jù)庫的連接,這一點我們可以理解,畢竟目前所有的應(yīng)用服務(wù)器取數(shù)據(jù)庫連接的方式都是這種方式實現(xiàn)的。但是另外一個共同的問題是,它們同時不允許使用者顯式的調(diào)用Connection.close()方法,而需要用其規(guī)定的一個方法來關(guān)閉連接。這種做

2、法有兩個缺點: 第一:改變了用戶使用習(xí)慣,增加了用戶的使用難度。 首先我們來看看一個正常的數(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.c

3、lose(); }catch(Exception e){} try{ conn.close();// }catch(Exception e){} } return res; } 使用者在用完數(shù)據(jù)庫連接后通常是直接調(diào)用連接的方法close來釋放數(shù)據(jù)庫資源,如果用我們前面提到的連接池的實現(xiàn)方法,那語句conn.close()將被某些特定的語句所替代。 第二:使連接池?zé)o法對之中的所有連接進行獨占控制。由于連接池不允許用戶直接調(diào)用連接的close方法,一旦使用者在使用的過程中由于習(xí)慣問題直接關(guān)閉了數(shù)據(jù)庫

4、連接,那么連接池將無法正常維護所有連接的狀態(tài),考慮連接池和應(yīng)用由不同開發(fā)人員實現(xiàn)時這種問題更容易出現(xiàn)。 綜合上面提到的兩個問題,我們來討論一下如何解決這兩個要命的問題。 首先我們先設(shè)身處地的考慮一下用戶是想怎么樣來使用這個數(shù)據(jù)庫連接池的。用戶可以通過特定的方法來獲取數(shù)據(jù)庫的連接,同時這個連接的類型應(yīng)該是標(biāo)準(zhǔn)的。用戶在獲取到這個數(shù)據(jù)庫連接后可以對這個連接進行任意的操作,包括關(guān)閉連接等。 通過對用戶使用的描述,怎樣可以接管Connection.close方法就成了我們這篇文章的主題。 為了接管數(shù)據(jù)庫連接的close方法,我們應(yīng)該有一種類似于鉤子的機制。例如在Windows編程中我們可以利用

5、Hook API來實現(xiàn)對某個Windows API的接管。在JAVA中同樣也有這樣一個機制。JAVA提供了一個Proxy類和一個InvocationHandler,這兩個類都在包中。我們先來看看SUN公司提供的文檔是怎么描述這兩個類的。 public interface InvocationHandler InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation

6、 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文檔中關(guān)于Proxy的描述很多,這里就不羅列出來。通過文檔對接口InvocationHandler的描述我們可以看到當(dāng)調(diào)用一個Proxy實例的方法時會觸發(fā)Invocationhanlder的invoke方法。從JAVA的文檔中我們也同時了解

7、到這種動態(tài)代理機制只能接管接口的方法,而對一般的類無效,考慮到本身也是一個接口由此就找到了解決如何接管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 use

8、r; //數(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; //取連接的時候如果沒有可用連接最大的等待時間 其次是連接池都工廠類ConnectionFac

9、tory,通過該類來將一個連接池對象與一個名稱對應(yīng)起來,使用者通過該名稱就可以獲取指定的連接池對象,具體代碼如下: /** * 連接池類廠,該類長用來保存多個數(shù)據(jù)源名稱合數(shù)據(jù)庫連接池對應(yīng)的哈希 * @author liusoft */ public class ConnectionFactory { //該哈希表用來保存數(shù)據(jù)源名和連接池對象的關(guān)系表 static Hashtable connectionPools = null; static{ connectionPools = new Hashtable(2,0.75F); } /** *

10、 從連接池工廠中獲取指定名稱對應(yīng)的連接池對象 * @param dataSource 連接池對象對應(yīng)的名稱 * @return DataSource 返回名稱對應(yīng)的連接池對象 * @throws NameNotFoundException 無法找到指定的連接池 */ public static DataSource lookup(String dataSource) throws NameNotFoundException { Object ds = null; ds = connectionPools.get(dataSource);

11、 if(ds == null || !(ds instanceof DataSource)) throw new NameNotFoundException(dataSource); return (DataSource)ds; } /** * 將指定的名字和數(shù)據(jù)庫連接配置綁定在一起并初始化數(shù)據(jù)庫連接池 * @param name 對應(yīng)連接池的名稱 * @param param 連接池的配置參數(shù),具體請見類ConnectionParam * @return DataSource 如果綁定成功后返回連接池對象 * @throws Name

12、AlreadyBoundException 一定名字name已經(jīng)綁定則拋出該異常 * @throws ClassNotFoundException 無法找到連接池的配置中的驅(qū)動程序類 * @throws IllegalAccessException 連接池配置中的驅(qū)動程序類有誤 * @throws InstantiationException 無法實例化驅(qū)動程序類 * @throws SQLException 無法正常連接指定的數(shù)據(jù)庫 */ public static DataSource bind(String name, ConnectionP

13、aram param) throws NameAlreadyBoundException,ClassNotFoundException, IllegalAccessException,InstantiationException,SQLException { DataSourceImpl source = null; try{ lookup(name); throw new NameAlreadyBoundException(name); }catch(NameNotFoundException e){ source = new D

14、ataSourceImpl(param); source.initConnection(); connectionPools.put(name, source); } return source; } /** * 重新綁定數(shù)據(jù)庫連接池 * @param name 對應(yīng)連接池的名稱 * @param param 連接池的配置參數(shù),具體請見類ConnectionParam * @return DataSource 如果綁定成功后返回連接池對象 * @throws NameAlreadyBoundException 一定名字name

15、已經(jīng)綁定則拋出該異常 * @throws ClassNotFoundException 無法找到連接池的配置中的驅(qū)動程序類 * @throws IllegalAccessException 連接池配置中的驅(qū)動程序類有誤 * @throws InstantiationException 無法實例化驅(qū)動程序類 * @throws SQLException 無法正常連接指定的數(shù)據(jù)庫 */ public static DataSource rebind(String name, ConnectionParam param) throws NameAl

16、readyBoundException,ClassNotFoundException, IllegalAccessException,InstantiationException,SQLException { try{ unbind(name); }catch(Exception e){} return bind(name, param); } /** * 刪除一個數(shù)據(jù)庫連接池對象 * @param name * @throws NameNotFoundException */ public static void u

17、nbind(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; }

18、} connectionPools.remove(name); } } ConnectionFactory主要提供了用戶將將連接池綁定到一個具體的名稱上以及取消綁定的操作。使用者只需要關(guān)心這兩個類即可使用數(shù)據(jù)庫連接池的功能。下面我們給出一段如何使用連接池的代碼: String name = "pool"; String driver = " "; String url = "jdbc:odbc:datasource"; ConnectionParam param = new ConnectionParam(driver,url,null,null);

19、 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(in

20、t 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 d

21、atasource ok."); System.exit(0); } 從使用者的示例代碼就可以看出,我們已經(jīng)解決了常規(guī)連接池產(chǎn)生的兩個問題。但是我們最最關(guān)心的是如何解決接管close方法的辦法。接管工作主要在ConnectionFactory中的兩句代碼: source = new DataSourceImpl(param); source.initConnection(); DataSourceImpl是一個實現(xiàn)了接口的類,該類維護著一個連接池的對象。由于該類是一個受保護的類,因此它暴露給使用者的方法只有接口DataSource中定義的方法,其他的所有方法對使用者來

22、說都是不可視的。我們先來關(guān)心用戶可訪問的一個方法getConnection /** * @see javax.sql.DataSource#getConnection(String,String) */ public Connection getConnection(String user, String password) throws SQLException { //首先從連接池中找出空閑的對象 Connection conn = getFreeConnection(0); if(conn == null){ //判斷是否超過最大連接數(shù),如果

23、超過最大連接數(shù) //則等待一定時間查看是否有空閑連接,否則拋出異常告訴用戶無可用連接 if(getConnectionCount() >= connParam.getMaxConnection()) conn = getFreeConnection(connParam.getWaitTime()); else{//沒有超過連接數(shù),重新獲取一個數(shù)據(jù)庫的連接 connParam.setUser(user); connParam.setPassword(password); Connection conn2 = DriverManage

24、r.getConnection(connParam.getUrl(), user, password); //代理將要返回的連接對象 _Connection _conn = new _Connection(conn2,true); synchronized(conns){ conns.add(_conn); } conn = _conn.getConnection(); } } return conn; } /** * 從連接池中取一個空閑的連接 * @param nTimeout

25、 如果該參數(shù)值為0則沒有連接時只是返回一個null * 否則的話等待nTimeout毫秒看是否還有空閑連接,如果沒有拋出異常 * @return Connection * @throws SQLException */ protected synchronized Connection getFreeConnection(long nTimeout) throws SQLException { Connection conn = null; Iterator iter = conns.iterator(); while(iter.has

26、Next()){ _Connection _conn = (_Connection)iter.next(); if(!_conn.isInUse()){ conn = _conn.getConnection(); _conn.setInUse(true); break; } } if(conn == null && nTimeout > 0){ //等待nTimeout毫秒以便看是否有空閑連接 try{ Thread.sleep(nTimeout); }catch(Exception e

27、){} conn = getFreeConnection(0); if(conn == null) throw new SQLException("沒有可用的數(shù)據(jù)庫連接"); } return conn; } DataSourceImpl類中實現(xiàn)getConnection方法的跟正常的數(shù)據(jù)庫連接池的邏輯是一致的,首先判斷是否有空閑的連接,如果沒有的話判斷連接數(shù)是否已經(jīng)超過最大連接數(shù)等等的一些邏輯。但是有一點不同的是通過DriverManager得到的數(shù)據(jù)庫連接并不是及時返回的,而是通過一個叫_Connection的類中介一下,然后調(diào)用_Conne

28、ction.getConnection返回的。如果我們沒有通過一個中介也就是JAVA中的Proxy來接管要返回的接口對象,那么我們就沒有辦法截住Connection.close方法。 終于到了核心所在,我們先來看看_Connection是如何實現(xiàn)的,然后再介紹是客戶端調(diào)用Connection.close方法時走的是怎樣一個流程,為什么并沒有真正的關(guān)閉連接。 /** * 數(shù)據(jù)連接的自封裝,屏蔽了close方法 * @author Liudong */ class _Connection implements InvocationHandler { private fina

29、l static String CLOSE_METHOD_NAME = "close"; private Connection conn = null; //數(shù)據(jù)庫的忙狀態(tài) private boolean inUse = false; //用戶最后一次訪問該連接方法的時間 private long lastAccessTime = System.currentTimeMillis(); _Connection(Connection conn, boolean inUse){ this.conn = conn; this.inUse = inUse;

30、 } /** * Returns the conn. * @return Connection */ public Connection getConnection() { //返回數(shù)據(jù)庫連接conn的接管類,以便截住close方法 Connection conn2 = (Connection)Proxy.newProxyInstance( conn.getClass().getClassLoader(), conn.getClass().getInterfaces(),this); return conn2; } /**

31、 * 該方法真正的關(guān)閉了數(shù)據(jù)庫的連接 * @throws SQLException */ void close() throws SQLException{ //由于類屬性conn是沒有被接管的連接,因此一旦調(diào)用close方法后就直接關(guān)閉連接 conn.close(); } /** * Returns the inUse. * @return boolean */ public boolean isInUse() { return inUse; } /** * @see java.lang.reflect.In

32、vocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object) */ public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { Object obj = null; //判斷是否調(diào)用了close的方法,如果調(diào)用close方法則把連接置為無用狀態(tài) if(CLOSE_METHOD_NAME.equals(m.getName())) setInUs

33、e(false); else obj = m.invoke(conn, args); //設(shè)置最后一次訪問時間,以便及時清除超時的連接 lastAccessTime = System.currentTimeMillis(); return obj; } /** * Returns the lastAccessTime. * @return long */ public long getLastAccessTime() { return lastAccessTime; } /** * Sets t

34、he inUse. * @param inUse The inUse to set */ public void setInUse(boolean inUse) { this.inUse = inUse; } } 一旦使用者調(diào)用所得到連接的close方法,由于用戶的連接對象是經(jīng)過接管后的對象,因此JAVA虛擬機會首先調(diào)用_Connection.invoke方法,在該方法中首先判斷是否為close方法,如果不是則將代碼轉(zhuǎn)給真正的沒有被接管的連接對象conn。否則的話只是簡單的將該連接的狀態(tài)設(shè)置為可用。到此您可能就明白了整個接管的過程,但是同時也有一個疑問:這樣的

35、話是不是這些已建立的連接就始終沒有辦法真正關(guān)閉?答案是可以的。我們來看看ConnectionFactory.unbind方法,該方法首先找到名字對應(yīng)的連接池對象,然后關(guān)閉該連接池中的所有連接并刪除掉連接池。在DataSourceImpl類中定義了一個close方法用來關(guān)閉所有的連接,詳細(xì)代碼如下: /** * 關(guān)閉該連接池中的所有數(shù)據(jù)庫連接 * @return int 返回被關(guān)閉連接的個數(shù) * @throws SQLException */ public int close() throws SQLException { int cc = 0;

36、 SQLException excp = null; Iterator iter = conns.iterator(); while(iter.hasNext()){ try{ ((_Connection)iter.next()).close(); cc ++; }catch(Exception e){ if(e instanceof SQLException) excp = (SQLException)e; } } if(excp != null) throw excp; return cc; } 該方法一一調(diào)用連接池中每個對象的close方法,這個close方法對應(yīng)的是_Connection中對close的實現(xiàn),在_Connection定義中關(guān)閉數(shù)據(jù)庫連接的時候是直接調(diào)用沒有經(jīng)過接管的對象的關(guān)閉方法,因此該close方法真正的釋放了數(shù)據(jù)庫資源。 以上文字只是描述了接口方法的接管,具體一個實用的連接池模塊還需要對空閑連接的監(jiān)控并及時釋放連接,詳細(xì)的代碼請參照附件。

展開閱讀全文
溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!