你的位置:首页 > Java教程

[Java教程]java学习笔记—JDBC6(21)


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方法进行拦截。