设计模式——动态代理

来源:互联网 发布:易语言编程软件下载 编辑:程序博客网 时间:2024/05/01 13:05
思考题
  1. 什么叫动态代理?
  2. 为什么使用动态代理?
  3. 什么地方可以使用动态代理?
动态代理的使用
  1. Proxy 类两个重要方法
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
             第一个参数:被代理类的装载器
             第二个参数:被代理类的接口
             第三个参数:处理类
    public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces),返回的就是代理类
  2. InvocationHandler  接口 ,一般的处理类会实现这个类,一个重要的方法
    Object invoke(Object proxy, Method method, Object[] args) 第一个参数:Proxy. newProxyInstance()生成的代理类 ,第二个参数:被代理的方法 ,第三个参数:被代理方法的参数    。
  3. 使用

Java代码 
  1. public interface Person {  
  2.     public void run();  
  3. }  
  4.   
  5. public class Man implements Person {//person接口的实现类  
  6.     @Override  
  7.     public void run() {  
  8.         System.out.println("-----");  
  9.     }  
  10. }  
  11.   
  12. public class TimeProxy implements InvocationHandler {// 被代理对象实例的处理程序  
  13.     private Object obj;// 被代理的类  
  14.       
  15.     public TimeProxy(Object obj) {  
  16.         super();  
  17.         this.obj = obj;  
  18.     }  
  19.     /** 
  20.      * proxy 动态生成的代理的类,其原理可理解为: 
  21.      *         当将其转化成java类,是一个继承了一个接口类, 
  22.      *         并在这个类里重载了接口的方法,而在这个方法里会调用此invoke方法; 
  23.      * method 被代理类的方法 
  24.      * args  代理类方法的参数 
  25.      */  
  26.     @Override  
  27.     public Object invoke(Object proxy, Method method, Object[] args)  
  28.             throws Throwable {// 处理代理实例的方法,并加上自己的需求  
  29.         doBefore();  
  30.         method.invoke(obj,  args);  
  31.         doAfter();  
  32.         return null;  
  33.     }  
  34.   
  35.     private void doAfter() {  
  36.         System.out.println("Start");  
  37.     }  
  38.   
  39.     private void doBefore() {  
  40.         System.out.println("end");  
  41.     }  
  42.   
  43. }  

 Java代码 

  1. public static void main(String[] args) {  
  2.         // TODO Auto-generated method stub  
  3.         Man man = new Man();  
  4.         TimeProxy timeProxy = new TimeProxy(man);  
  5.         Person person = (Person)Proxy.newProxyInstance(man.getClass().getClassLoader(), man.getClass().getInterfaces(), timeProxy);  
  6.         person.run();                                                                 
  7.     }  

 1、原理:实际效果,就是相当与动态的生成以下一个类

  1. Java代码 
    1. public class TimeProxy1 implements Person {// 这种方式只是适合某一个对象的代理,  
    2.     //但是不够灵活  
    3.     private Person person;  
    4.     public TimeProxy1(Person person) {  
    5.         super();  
    6.         this.person = person;  
    7.     }  
    8.     @Override  
    9.     public void run() {  
    10.         System.out.println("Start");  
    11.         person.run();  
    12.         System.out.println("end");  
    13.     }  
    14. }   
      
  2. 如何动态实现
    Java代码 
    1. public class Test1 {  
    2.     public static Object newProxyInstance() throws Exception{  
    3.         String rt = "\r\n";  
    4.         String src =   
    5.             "package com.ps.proxy;" +  rt +  
    6.             "public class TimeProxy1 implements Person {" + rt +  
    7.             "    public TimeProxy1(Person p) {" + rt +  
    8.             "        super();" + rt +  
    9.             "        this.p = p;" + rt +  
    10.             "    }" + rt +  
    11.               
    12.             "    Person p;" + rt +  
    13.                               
    14.             "    @Override" + rt +  
    15.             "    public void run() {" + rt +  
    16.             "        System.out.println(\"start\" );" + rt +  
    17.             "        p.run();" + rt +  
    18.             "        System.out.println(\"end\" );" + rt +  
    19.             "    }" + rt +  
    20.             "}";  
    21.         // 写文件  
    22.         String fileName = "d:/src/com/ps/proxy/TimeProxy1.java";  
    23.         File f = new File(fileName);  
    24.         FileWriter fw = new FileWriter(f);  
    25.         fw.write(src);  
    26.         fw.flush();  
    27.         fw.close();  
    28.                                                                                      
    29.         //编译  
    30.         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();  
    31.         StandardJavaFileManager fileMgr = compiler.getStandardFileManager(nullnull,null);  
    32.         Iterable units = fileMgr.getJavaFileObjects(fileName);  
    33.         CompilationTask t = compiler.getTask(null, fileMgr, nullnullnull, units);
    34.         t.call();  
    35.         fileMgr.close();  
    36.           
    37.         //将class文件加载到内存                                                        
    38.         URL[] urls = new URL[] {new URL("file:/d:/src")};  
    39.         URLClassLoader ul = new URLClassLoader(urls);  
    40.         Class c = ul.loadClass("TimeProxy1");  
    41.         System.out.println(c);  
    42.           
    43.         Constructor ctr = c.getConstructor(Person.class);  
    44.         Person person = (Person)ctr.newInstance(new Man());//相当得到代理
    45. //类的一个实例  
    46.         return person;  
    47.     }  
    48. }  

    为更多类实现代理
     Java代码 

    1. public class Proxy {  
    2.     public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception {   
    3.         String methodStr = "";  
    4.         String rt = "\r\n";  
    5.         Method[] methods = infce.getMethods();  
    6.           
    7.         for(Method m : methods) {  
    8.             methodStr += "    @Override" + rt +   
    9.                          "    public void " + m.getName() + "() {" + rt +  
    10.                          "        try {" + rt +  
    11.                          "        Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +  
    12.                          "        h.invoke(this, md);" + rt +  
    13.                          "    }catch(Exception e) {e.printStackTrace();}" + rt +  
    14.                           
    15.                          "}";  
    16.         }  
    17.           
    18.         String src =   
    19.             "package com.ps.proxy;" +  rt +  
    20.             "import java.lang.reflect.Method;" + rt +  
    21.             "public class Proxy1 implements " + infce.getName() + "{" + rt +  
    22.             "    public Proxy1(InvocationHandler h) {" + rt +  
    23.             "        this.h = h;" + rt +  
    24.             "    }" + rt +  
    25.               
    26.               
    27.             "    com.ps.proxy.InvocationHandler h;" + rt +  
    28.                               
    29.             methodStr +  
    30.             "}";  
    31.         // 写文件  
    32.         String fileName = "d:/src/com/ps/proxy/Proxy1.java";  
    33.         File f = new File(fileName);  
    34.         FileWriter fw = new FileWriter(f);  
    35.         fw.write(src);  
    36.         fw.flush();  
    37.         fw.close();  
    38.           
    39.         //编译  
    40.         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();  
    41.         StandardJavaFileManager fileMgr = compiler.getStandardFileManager(nullnull,null);  
    42.         Iterable units = fileMgr.getJavaFileObjects(fileName);  
    43.         CompilationTask t = compiler.getTask(null, fileMgr, nullnullnull, units);
    44.         t.call();  
    45.         fileMgr.close();  
    46.           
    47.         //加载到内存  
    48.         URL[] urls = new URL[] {new URL("file:/"+"d:/src/")};  
    49.         URLClassLoader ul = new URLClassLoader(urls);  
    50.         Class c = ul.loadClass("com.ps.proxy.Proxy1");  
    51.         System.out.println(c);  
    52.           
    53.           
    54.         Constructor ctr = c.getConstructor(InvocationHandler.class);  
    55.         Object m = ctr.newInstance(h);  
    56.         //m.move();  
    57.   
    58.         return m;  
    59.     }  
    60. }  

    处理类所需要做的事 

    Java代码 

    1. public interface InvocationHandler {//定义一个借口  
    2.     public void invoke(Object o, Method m);  
    3. }  
    4. public class TimeHandler implements InvocationHandler{//借口实现类  
    5.     private Object target;  
    6.   
    7.     public TimeHandler(Object target) {  
    8.         super();  
    9.         this.target = target;//要处理的实际对象  
    10.     }  
    11.   
    12.     @Override  
    13.     public void invoke(Object o, Method m) {//o就是生产的代理类  
    14.         // m被代理的方法  
    15.         System.out.println("start");  
    16.         try {  
    17.             m.invoke(target);  
    18.         } catch (Exception e) {  
    19.             e.printStackTrace();  
    20.         }  
    21.         System.out.println("end");  
    22.     }  
    23. }  



  3. 答案:
    1. 创建代理对象,代理对象能实现一个或多个已知接口,并用反射代替内置的虚方法,动态的实现对接口方法的调用。这个过程允许实现“截取”方法调用,重新路由它们或者动态地添加功能。
      动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不 知道它是与代理打交道还是与实际对象打交道。
    2. 使用第三方的接口,权限管理,写日志等

0 0
原创粉丝点击