1 用動態代理書寫連接池
設計:
代理的目標:原生的connection。
代理的目的:修改close方法,讓close方法不可以關閉連接,且主動收回連接。
通過動態代理,和線程通訊:
1:對Cxonnection進行代理。
2:在獲取Connection時,通過同步,如果沒有連接時,就讓線程進入等待池。
3:修改close方法,且在還了連接以后喚醒正在等待的線程。
package cn.itcast.utils;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.PRoxy;import java.sql.Connection;import java.sql.DriverManager;import java.util.ArrayList;import java.util.List;public class ConnUtils3 { //第一步:聲明連接池維護所有的連接 private static List<Connection> pool = new ArrayList<Connection>(); //第二步:靜態代碼塊中創建多個連接 static{ try{ Class.forName("com.MySQL.jdbc.Driver"); String url = "jdbc:mysql:///db909?characterEncoding=UTF8"; for(int i=0;i<3;i++){ final Connection con = DriverManager.getConnection(url,"root","1234");//com.mysql.jdbc.Jdbc4Connection@ //對con對象進行動態代理 Object proxyedCon = Proxy.newProxyInstance( ConnUtils3.class.getClassLoader(), new Class[]{Connection.class}, //聲明執行句柄,只對close方法設置攔截 new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("close")){ System.err.println("有人想關閉連接,不能關,還連接"); //將proxy再加到pool中,這個proxy就是proxyedCon synchronized (pool) { pool.add((Connection) proxy); pool.notify(); } return null; }else{ System.err.println("放行"+method.getName()); return method.invoke(con, args); } } }); //一定要將代理對象添加到池中去。 pool.add((Connection) proxyedCon); } }catch(Exception e){ throw new RuntimeException(e.getMessage(),e); } } /** * 提供一個靜態工廠方法返回一個連接 */ public static Connection getCon(){ synchronized (pool) { if(pool.size()==0){ try { pool.wait(); } catch (InterruptedException e) { e.printStackTrace(); } return getCon(); } Connection con = pool.remove(0);//返回一個代理的connection對象 System.err.println("還有幾個:"+pool.size()); return con; } }}
優化代碼
通過類加載器讀取一個資源文件:
SomeClass.class.getReesource(xxx) – 獲取與SomeCalss字節碼同一個目錄下的xxx文件。
SomeClass.class.getClassLoader().getResource(“xxxx”); - 獲取classpath根下上的xxx文件。
1:將url,driver,name,pwd寫到一個配置文件中去。-properties
2:通過LinkedList來維護一個池。
讀取資源文件,獲取信息
//聲明資源器類 - Properties prop = new Properties(); //獲取這個文件的路徑 URL url = ConnUtils3.class.getClassLoader().getResource("jdbc.properties"); String path = url.getPath(); //為了防止有中文或是空格 path = URLDecoder.decode(path,"UTf-8"); File file = new File(path); //加載jdbc.properties這個文件 prop.load(new FileInputStream(file)); //獲取信息 String driver = prop.getProperty("driver"); Class.forName(driver); String jdbcurl = prop.getProperty("url"); String nm = prop.getProperty("name"); String pwd = prop.getProperty("pwd"); //創建三個原生的連接,都將它們代理 String poolSize = prop.getProperty("poolSize"); int size = Integer.parseInt(poolSize); for(int i=0;i<size;i++){ //創建多個連接,代理每一個連接。攔截close方法,還連接。連接池的作用1:維護多個連接。
在初始化時創建List,將多個連接放到List中去.
2:可以在close時回收連接
對Connection進行動態代理,
對close方法進行攔截。
新聞熱點
疑難解答