数据库连接池代理实现(代理设计模式)-续数据库连接池

来源:互联网 发布:w7怎么切换网络连接 编辑:程序博客网 时间:2024/06/05 05:49
在代码中调用close时也可以还连接

对close方法进行修改。


类加载器



系统加载字节码是从下层往上层找的  如果父类没有就继续找父类 找到根加载器之后再往下加载    系统不允许操作根加载器  所以返回值永远是null、


动态代理

作用:
1:对某个方法增强。
2:在不污染源类的情况下,修改原类的行为。 
代理类,与被代理类,两个不同的实体。
要求:
所有被代理的类,都必须要拥有一个接口。

本质上是对方法进行修改,但其实它是通过反射执行的某个方法。

动态代理的核心类

Proxy – 用于创建给定接口的子类,在内存中动态的创建。$Proxy0. - 此类只使用一次。InovocationHandler – 执行句柄。在执行时可以获取被代理类的所有反射。 - 用户的每一次调用都会被这个句柄拦截到。

代理举例

被代理类实现的接口

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public interface IGDG {  
  2.     String talk();  
  3. }  


被代理类
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class GDG implements IGDG {  
  2.     int nu = 0;  
  3.     public GDG(int nm) {  
  4.         nu=nm;  
  5.     }  
  6.     public String talk(){  
  7.         System.err.println("5.1:开始讲了....."+nu);  
  8.         return "你好:"+nu;  
  9.     }  
  10. }  





代理实现
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class ProxyDemo {  
  2.     public static void main(String[] args) throws Exception {  
  3.         final Object o = new GDG(3);//匿名内部类只能访问final成员  
  4.         System.err.println("o1 is:"+o+","+o.getClass());//GDG@4a5ab2,class cn.itcast.demo.GDG  
  5.         //使用Proxy类创建IGDG接口的子类  
  6.         Object proxyedObj =   
  7.                 Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(), //用哪一个类加载器在内存中加载一个IGDG的子类  
  8.                                       new Class[]{IGDG.class},//创建哪些接口的子类   
  9.                                       new InvocationHandler(){  
  10.                                         public Object invoke(Object proxy,  
  11.                                                 Method method, Object[] args)  
  12.                                                 throws Throwable {  
  13.                                             System.err.println("你正在执行的方法名为:"+method.getName());  
  14.                                             Object returnValue = method.invoke(o,args);  
  15.                                             return returnValue;  
  16.                                         }  
  17.                                     });  
  18.         //将proxyedObj强转成IGDG  
  19.         IGDG o2 = (IGDG) proxyedObj;  
  20.         o2.talk();  
  21.         System.err.println("-------");  
  22.         System.err.println("o2 is:"+o2+","+o2.getClass());  
  23.     }  




仔细讲解
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class ProxyDemo2 {  
  2.     public static void main(String[] args) throws Exception {  
  3.         final GDG o = new GDG(4);  
  4.         System.err.println("1:声明被代理的对象"+o+","+o.getClass());  
  5.         Object proxyedObj =   
  6.                 Proxy.newProxyInstance(  
  7.                         ProxyDemo2.class.getClassLoader(),  
  8.                         new Class[]{IGDG.class},//必须填接口  
  9.                         new InvocationHandler() {  
  10.                             public Object invoke(Object proxy, Method method, Object[] args)  
  11.                                     throws Throwable {  
  12.                                 System.err.println("5:正在调用的方法是:"+method.getName());//talk  
  13.                                 Object returnValue = method.invoke(o,args);  
  14.                                 System.err.println("6:通过反射调用目标(被代理类)类的方法成功,返回值是:"+returnValue);  
  15.                                 return "你不好";  
  16.                             }  
  17.                         }  
  18.                     );  
  19.           
  20.         System.err.println("2:代理类创建完成:"+proxyedObj.getClass());  
  21.         System.err.println("3:强转成IGDG接口");  
  22.         IGDG o2 = (IGDG) proxyedObj;  
  23.         System.err.println("4:调用代理类的talk方法");  
  24.         String back = o2.talk();  
  25.         System.err.println("7:方法都调用完成\t"+back);  
  26.     }  
  27. }  



[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. 输出结果  
  2. 1:声明被代理的对象cn.itcast.demo.GDG@1c68b6f,class cn.itcast.demo.GDG  
  3. 2:代理类创建完成:class com.sun.proxy.$Proxy0  
  4. 3:强转成IGDG接口  
  5. 4:调用代理类的talk方法  
  6. 5:正在调用的方法是:talk  
  7. 5.1:开始讲了.....4  
  8. 6:通过反射调用目标(被代理类)类的方法成功,返回值是:你好:4  
  9. 7:方法都调用完成   你不好  


代理list

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class ListProxy {  
  2.     public static void main(String[] args) throws Exception {  
  3.         final List list = new ArrayList();  
  4.         //声明代理  
  5.         Object oo = Proxy.newProxyInstance(  
  6.                 ListProxy.class.getClassLoader(),  
  7.                 new Class[]{List.class}  
  8.                 ,  
  9.                 new InvocationHandler() {  
  10.                     public Object invoke(Object proxy, Method method, Object[] args)  
  11.                             throws Throwable {  
  12.                         //执行被代理类的方法  
  13.                         System.err.println("正在执行的方法是:"+method.getName());  
  14.                         if(args!=null){  
  15.                             for(Object arg:args){  
  16.                                 System.err.println("参数:"+arg);  
  17.                             }  
  18.                         }  
  19.                         Object returnVal = method.invoke(list,args);  
  20.                         if(method.getName().equals("size")){//调用的是否是size方法  
  21.                             System.err.println("其实是:"+returnVal);  
  22.                             return 1000;  
  23.                         }  
  24.                         return returnVal;  
  25.                     }  
  26.                 });  
  27.           
  28.         List list2 = (List) oo;  
  29. //      list2.add("Jack");  
  30. //        
  31. //      int size = list2.size();  
  32. //      System.err.println("大小是:"+size);  
  33. //        
  34.         System.err.println("-----------");  
  35.         list.add("Rose");//1  
  36.         list.add("Jack");  
  37.         System.err.println("=====================");  
  38.         int size = list2.size();  
  39.         System.err.println("大小是:"+size);//1  
  40.     }  
  41. }  


代理的任务

1:在内存中创建某个接口的子类。
2:拦截所有在代理上执行的方法。( 除了getClass方法。)

用动态代理书写连接池

设计:
代理的目标:原生的connection。
  代理的目的:修改close方法,让close方法不可以关闭连接,且主动收回连接。

通过动态代理,和线程通讯:
1:对Cxonnection进行代理。
 2:在获取Connection时,通过同步,如果没有连接时,就让线程进入等待池。
 3:修改close方法,且在还了连接以后唤醒正在等待的线程。


[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class ConnUtils4 {  
  2.     //第一步:声明连接池维护所有的连接  
  3.     private static List<Connection> pool = new ArrayList<Connection>();  
  4.     //第二步:静态代码块中创建多个连接  
  5.     static{  
  6.         try{  
  7.             Class.forName("com.mysql.jdbc.Driver");  
  8.             String url = "jdbc:mysql:///db909?characterEncoding=UTF8";  
  9.             for(int i=0;i<3;i++){  
  10.                 final Connection con = DriverManager.getConnection(url,"root","1234");//com.mysql.jdbc.Jdbc4Connection@  
  11.                 //对con对象进行动态代理  
  12.                 Object proxyedCon =   
  13.                         Proxy.newProxyInstance(  
  14.                                 ConnUtils4.class.getClassLoader(),  
  15.                                 new Class[]{Connection.class},  
  16.                                 //声明执行句柄,只对close方法设置拦截  
  17.                                 new InvocationHandler() {  
  18.                                     public Object invoke(Object proxy, Method method, Object[] args)  
  19.                                             throws Throwable {  
  20.                                         if(method.getName().equals("close")){  
  21.                                             System.err.println("有人想关闭连接,不能关,还连接");  
  22.                                             //将proxy再加到pool中,这个proxy就是proxyedCon  
  23.                                             synchronized (pool) {  
  24.                                                 pool.add((Connection) proxy);  
  25.                                                 pool.notify();  
  26.                                             }  
  27.                                             return null;  
  28.                                         }else{  
  29.                                             System.err.println("放行"+method.getName());  
  30.                                             return method.invoke(con, args);  
  31.                                         }  
  32.                                     }  
  33.                                 });  
  34.                   
  35.                   
  36.                   
  37.                   
  38.                   
  39.                   
  40.                 //一定要将代理对象添加到池中去。  
  41.                 pool.add((Connection) proxyedCon);  
  42.             }  
  43.         }catch(Exception e){  
  44.             throw new RuntimeException(e.getMessage(),e);  
  45.         }  
  46.     }  
  47.     /** 
  48.      * 提供一个静态工厂方法返回一个连接 
  49.      */  
  50.     public static Connection getCon(){  
  51.         synchronized (pool) {  
  52.             if(pool.size()==0){  
  53.                 try {  
  54.                     pool.wait();  
  55.                 } catch (InterruptedException e) {  
  56.                     e.printStackTrace();  
  57.                 }  
  58.                 return getCon();  
  59.             }  
  60.             Connection con = pool.remove(0);//返回一个代理的connection对象  
  61.             System.err.println("还有几个:"+pool.size());  
  62.             return con;  
  63.         }  
  64.     }  
  65. }  
0 0
原创粉丝点击