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方法进行拦截。
新闻热点
疑难解答