Java-马士兵动态代理模式

模拟jdk的动态代理的实现原理, 这些东西没有必要写出来,写项目的时候一般用不上,主要是为了面试和理解原理;

java动态代理有什么作用

作用非常大,在很多底层框架中都会用得到,比如struts,Spring等都用到了动态代理,它的作用很简单,就是将你要使用的类,重新生成一个子类或本类,这样框架就可以利用这个新生成的类做一些事情,比如在该类的方法前后加一些代码。。
这样的话,你想像一下,你是不是不用修改任何已经编写好的代码,只要使用代理就可以灵活的加入任何东西,将来不喜欢了,不用也不会影响原来的代码。

https://www.zhihu.com/question/20794107/answer/23334315

代理模式-聚合与继承方式比较

参考地址:http://www.cnblogs.com/shamgod/p/4591782.html

 

一、概述

1.目标:要在Tank的move()方法做时间代理及日志代理(可以设想以后还要增加很多代理处理),且代理间的顺序可活更换

2.思路:

(1)聚合:代理类聚合了被代理类,且代理类及被代理类都实现了movable接口,则可实现灵活多变,具体看代码

(2)继承:继承不够灵活,具体看代码

 
 

二、代码

1.Movable.java

2.Tank.java

3.TankTimeProxy.java

4.TankLogProxy.java

5.Tank2Time.java

6.Tank3Log.java

7.Client.java

 1.Movable.java

  1. public
    interface Movable {
  2.   public
    void move();
  3.  }

 
 

2.Tank.java

  1. import java.util.Random;
  2.  
  3. public
    class Tank implements Movable {
  4.  
  5.     @Override
  6.     public
    void move() {
  7.         System.out.println("Tank moving.......");
  8.         try {
  9.             Thread.sleep(new Random().nextInt(5000));
  10.         } catch (InterruptedException e) {
  11.             e.printStackTrace();
  12.         }
  13.     }
  14.  
  15. }

 
 

3.TankTimeProxy.java

  1. public
    class TankTimeProxy implements Movable {
  2.  
  3.     Movable m;
  4.  
  5.     public TankTimeProxy(Movable m) {
  6.         this.m = m;
  7.     }
  8.  
  9.     @Override
  10.     public
    void move() {
  11.         System.out.println("Time Proxy start...........");
  12.         long start = System.currentTimeMillis();
  13.         m.move();
  14.         long end = System.currentTimeMillis();
  15.         System.out.println("花费时间:"+(end - start));
  16.         System.out.println("Time Proxy end...........");
  17.     }
  18.  
  19. }

 

4.TankLogProxy.java

  1. public
    class TankLogProxy implements Movable {
  2.     Movable m;
  3.     public TankLogProxy(Movable m) {
  4.         this.m = m;
  5.     }
  6.     @Override
  7.     public
    void move() {
  8.         System.out.println("Log Proxy start...........");
  9.         m.move();
  10.         System.out.println("Log Proxy end...........");
  11.     }
  12. }

 
 

5.Tank2Time.java

  1. public
    class Tank2Time extends Tank {
  2.  
  3.     public
    void move(){
  4.         System.out.println("Tank2 time start...........");
  5.         long start = System.currentTimeMillis();
  6.         super.move();
  7.         long end = System.currentTimeMillis();
  8.         System.out.println("花费时间:"+(end - start));
  9.         System.out.println("Tank2 time end...........");
  10.     }
  11. }

 
 

6.Tank3Log.java

  1. public
    class Tank3Log extends Tank2Time {
  2.  
  3.     public
    void move(){
  4.         System.out.println("Tank3Log start...........");
  5.         super.move();
  6.         System.out.println("Tank3Log end...........");
  7.     }
  8. }

 
 

7.Client.java

  1. public
    class Client {
  2.  
  3.     @Test
  4.     public
    void testProxy(){
  5.         Tank t = new Tank();
  6.         Movable m;
  7.         //一、聚合的方式(较灵活,因为实现了接口)
  8.         //1.1聚合方式的代理,先日志代理,后时间代理
  9.         TankTimeProxy ttp1 = new TankTimeProxy(t);
  10.         TankLogProxy tlp1 = new TankLogProxy(ttp1);
  11.         m = tlp1;
  12.         m.move();
  13.         System.out.println("\n==============================分隔线==========================\n");
  14.         //1.2聚合方式的代理,先时间代理,后日志代理(可以灵活切换顺序)
  15.         TankLogProxy tlp2 = new TankLogProxy(t);
  16.         TankTimeProxy ttp2 = new TankTimeProxy(tlp2);
  17.         m = ttp2;
  18.         m.move();
  19.         System.out.println("\n==============================分隔线==========================\n");
  20.         //二、继承的方式
  21.         //2.1代理时间
  22.         Tank2Time t2 = new Tank2Time();
  23.         t2.move();
  24.         System.out.println("\n==============================分隔线==========================\n");
  25.         //2.2先代理日志,后时间,不能灵活切换
  26.         Tank3Log t3 = new Tank3Log();
  27.         t3.move();
  28.     }
  29. }

 
 

三、运行结果

 
 

四、小结

凡是要求灵活多变的功能,多数用接口多态实现

 

 

三:问题引出

每实现一个需求都需要写一个代理类,比如:为了实现在方法前后加日志TankLogProxy、为了实现记录方法运行时间TankTimeProxy,随着系统的复杂,如果还需要实现权限、事务管理,用这种设计方法,代理类会越来越多。有没有一种方式,能够让我们不写这些代理类? 动态代理,动态的去代理,代理类是动态生成的,不需要我们编写,这样就可以解决这个代理类很多的问题,这样会极大地减少了我们的工作。

 

 

 

 

 

代理模式-动态代理 调用Proxy.newProxyInstance()

http://www.cnblogs.com/shamgod/p/4592014.html

一、概述

1.目标:不自己写代理类,利用Proxy.newProxyInstance()动态生成

2.用到的知识点:

(1)//编译源码,生成class,注意编译环境要换成jdk1.6才有compiler,单纯的jre没有compiler,会空指针错误

JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
(2)//文件管事器
StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);
(3)//编译单元
Iterable units = fileMgr.getJavaFileObjects(file);
(4)//编译任务
CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);

(5)//编译
t.call();

(6)//把类load到内存里

URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.class")};
URLClassLoader uc = new URLClassLoader(urls);
Class c = uc.loadClass("proxy.TankTimeProxy");

(7)//生成实例

//return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
Constructor ctr = c.getConstructor(Movable.class);
return ctr.newInstance(new Tank());

 
 

二、代码

1.Movable.java

2.Tank.java

3.Proxy.java

4.Client.java

 1.Moveable.java

  1. package com.weiqinshian.proxy;
  2. public
    interface Moveable
  3. {
  4.    public
    void move();
  5. }

 

2.Tank.java

  1. package com.weiqinshian.proxy;
  2. import java.util.Random;
  3. public
    class Tank implements Moveable
  4. {
  5.    @Override
  6.    public
    void move()
  7.    {
  8.       System.out.println("tank move........");
  9.       try
  10.       {
  11.          Thread.sleep(new Random().nextInt(10000));
  12.       } catch (InterruptedException e)
  13.       {
  14.          e.printStackTrace();
  15.       }
  16.    }
  17. }

 

3.Proxy.java

  1. package com.weiqinshian.proxy;
  2. import java.io.File;
  3. import java.io.FileWriter;
  4. import java.lang.reflect.Constructor;
  5. import java.net.URL;
  6. import java.net.URLClassLoader;
  7. import javax.tools.JavaCompiler;
  8. import javax.tools.StandardJavaFileManager;
  9. import javax.tools.ToolProvider;
  10. import javax.tools.JavaCompiler.CompilationTask;
  11. public
    class Proxy
  12. {
  13.    public
    static Object newProxyInstance() throws Exception
  14.    {
  15.       String rt = "\n\r";
  16.       // 动态代理文件的源码
  17.       String str = "package com.weiqinshian.proxy;" + rt +
  18.       "public class TankTimeProxy implements Moveable {" + rt +
  19.       "private Moveable m;" + rt +
  20.       "public TankTimeProxy(Moveable m) {" + rt + "this.m = m;" + rt + "}" + rt +
  21.       "@Override" + rt + "public void move() {" + rt + "System.out.println(\"Time Proxy start...........\");" + rt + "long start = System.currentTimeMillis();" + rt + "m.move();" + rt
  22.             + "long end = System.currentTimeMillis();" + rt + "System.out.println(\"花费时间:\"+(end - start));" + rt + "System.out.println(\"Time Proxy end...........\");" + rt + "}" + rt +
  23.             "}";
  24.       // 把源码写到java文件里
  25.       File file = new File("d:/src/com/weiqinshian/proxy/TankTimeProxy.java");
  26.       FileWriter fw = new FileWriter(file);
  27.       fw.write(str);
  28.       fw.flush();
  29.       fw.close();
  30.       // 编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误
  31.       JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
  32.       // 文件管事器
  33.       StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);
  34.       // 编译单元
  35.       Iterable units = fileMgr.getJavaFileObjects(file);
  36.       // 编译任务
  37.       CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);
  38.       // 编译
  39.       t.call();
  40.       fileMgr.close();
  41.       // 把类load到内存里src\com\weiqinshian\proxy
  42.       URL[] urls = new URL[]
  43.       { new URL("file:/" + "d:/src/") };
  44.       System.out.println("file:/" + System.getProperty("user.dir") + "/src/com/weiqinshian/proxy/TankTimeProxy.class");
  45.       URLClassLoader uc = new URLClassLoader(urls);
  46.       Class c = uc.loadClass("com.weiqinshian.proxy.TankTimeProxy");
  47.       // 生成实例
  48.       // return c.newInstance();
  49.       // //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
  50.       Constructor ctr = c.getConstructor(Moveable.class);
  51.       return ctr.newInstance(new Tank());
  52.    }
  53. }

 
 

4.Client.java

  1.  package com.weiqinshian.proxy;
  2. public
    class Client
  3. {
  4.    public
    static
    void main(String[] args) throws Exception
  5.    {
  6.       Moveable m = (Moveable) Proxy.newProxyInstance();
  7.       m.move();// 感觉没有生成任何代理类
  8.    }
  9. }

三、运行结果

 
 

 

三、问题引出

现在动态代理,动态生成的代理类是写死了的,是用字符串写死在类里面的,而且,只能动态生成实现了 Moveable接口的代理,如果要实现任意接口的代理应该怎么办? 那就不将动态生成代理类的字符串写死,动态拼接生成代理类。

代理模式--动态代理 修改成可以代理任意接口

 

一、概述

1.目标:把Proxy修改成可以代理任意接口及其任意方法,只要传接口名给newProxyInstance,就能动态生成实现了该接口的代理类。

2.思路:

(1)代理任意接口:把接口类型作为参数传给Proxy的newProxyInstance(Class interfze)

(2)代理任意方法:用interfze.getMethods()取出所有方法,拼接实现方法的字符串

 
 

二、代码

1.Movable.java

2.Tank.java

3.Proxy.java

4.Client.java

 
 

1.Movable.java

  1. package com.weiqinshian.proxy;
  2. public
    interface Moveable
  3. {
  4.    public
    void move();
  5.    public
    void stop();
  6. }

 
 

2.Tank.java

  1. package com.weiqinshian.proxy;
  2. import java.util.Random;
  3. public
    class Tank implements Moveable
  4. {
  5.    @Override
  6.    public
    void move()
  7.    {
  8.       System.out.println("tank move........");
  9.       try
  10.       {
  11.          Thread.sleep(new Random().nextInt(10000));
  12.       } catch (InterruptedException e)
  13.       {
  14.          e.printStackTrace();
  15.       }
  16.    }
  17.    public
    void stop()
  18.    {
  19.       System.out.println("Tank stopping.......");
  20.    }
  21. }

 

3.Proxy.java

  1. package com.weiqinshian.proxy;
  2. import java.io.File;
  3. import java.io.FileWriter;
  4. import java.lang.reflect.Constructor;
  5. import java.lang.reflect.Method;
  6. import java.net.URL;
  7. import java.net.URLClassLoader;
  8. import javax.tools.JavaCompiler;
  9. import javax.tools.StandardJavaFileManager;
  10. import javax.tools.ToolProvider;
  11. import javax.tools.JavaCompiler.CompilationTask;
  12.  
  13. public
    class Proxy
  14. {
  15.    public
    static Object newProxyInstance(Class interfze) throws Exception
  16.    {
  17.       String rt = "\n\r";
  18.       // 拼接"实现接口方法"的字符串
  19.       String methodStr = "";
  20.       for (Method m : interfze.getMethods())
  21.       {
  22.          // 取出方法的修饰符和返回值类型
  23.          String[] parts = m.toString().replace("abstract ", "").split("\\.");
  24.          String[] parts2 = parts[0].split("
    ");
  25.          methodStr += "@Override" + rt + parts2[0] + "
    " + parts2[1] + "
    " + m.getName() + "() {" + rt + "System.out.println(\"Time Proxy start...........\");" + rt
  26.                + "long start = System.currentTimeMillis();" + rt + "m." + m.getName() + "();" + rt + "long end = System.currentTimeMillis();" + rt
  27.                + "System.out.println(\"花费时间:\"+(end - start));" + rt + "System.out.println(\"Time Proxy end...........\");" + rt + "}";
  28.       }
  29.       // 动态代理文件的源码
  30.       String str = "package com.weiqinshian.proxy; " + rt +
  31.       "public class TankTimeProxy implements " + interfze.getName() + " {" + rt +
  32.       "private " + interfze.getName() + " m;" + rt +
  33.       "public TankTimeProxy(" + interfze.getName() + " m) {" + rt + "this.m = m;" + rt + "}" + rt +
  34.       methodStr + rt +
  35.       "}";
  36.       // 把源码写到java文件里
  37.       File file = new File("d:/src/com/weiqinshian/proxy/TankTimeProxy.java");
  38.       FileWriter fw = new FileWriter(file);
  39.       fw.write(str);
  40.       fw.flush();
  41.       fw.close();
  42.       // 编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误
  43.       JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
  44.       // 文件管事器
  45.       StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);
  46.       // 编译单元
  47.       Iterable units = fileMgr.getJavaFileObjects(file);
  48.       // 编译任务
  49.       CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);
  50.       // 编译
  51.       t.call();
  52.       fileMgr.close();
  53.       // 把类load到内存里src\com\weiqinshian\proxy
  54.       URL[] urls = new URL[]
  55.       { new URL("file:/" + "d:/src/") };
  56.       System.out.println("file:/" + System.getProperty("user.dir") + "/src/com/weiqinshian/proxy/TankTimeProxy.class");
  57.       URLClassLoader uc = new URLClassLoader(urls);
  58.       Class c = uc.loadClass("com.weiqinshian.proxy.TankTimeProxy");
  59.       // 生成实例
  60.       // return c.newInstance();
  61.       // //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
  62.       Constructor ctr = c.getConstructor(interfze);
  63.       return ctr.newInstance(new Tank());
  64.    }
  65. }

 
 

4.Client.java

  1. package com.weiqinshian.proxy;
  2.  
  3. public
    class Client
  4. {
  5.    public
    static
    void main(String[] args) throws Exception
  6.    {
  7.       Moveable m = (Moveable) Proxy.newProxyInstance(Moveable.class);// 方法参数可以传任意接口类型
  8.       m.move();
  9.       m.stop();
  10.    }
  11. }

 

三、运行结果

TankTimeProxy 动态生成的类

  1. package com.weiqinshian.proxy;
  2. public
    class TankTimeProxy implements com.weiqinshian.proxy.Moveable {
  3.     private com.weiqinshian.proxy.Moveable m;
  4.     public TankTimeProxy(com.weiqinshian.proxy.Moveable m) {
  5.         this.m = m;
  6.     }
  7.     @Override
  8.     public
    void stop() {
  9.         System.out.println("Time Proxy start...........");
  10.         long start = System.currentTimeMillis();
  11.         m.stop();
  12.         long end = System.currentTimeMillis();
  13.         System.out.println("花费时间:" + (end - start));
  14.         System.out.println("Time Proxy end...........");
  15.     }
  16.     @Override
  17.     public
    void move() {
  18.         System.out.println("Time Proxy start...........");
  19.         long start = System.currentTimeMillis();
  20.         m.move();
  21.         long end = System.currentTimeMillis();
  22.         System.out.println("花费时间:" + (end - start));
  23.         System.out.println("Time Proxy end...........");
  24.     }
  25. }

四、问题引出

上面这种方式生成的动态代理,只能生成时间上的代理。我要想生成一个log、权限代理,还是需要再写一个Proxy动态代理类,怎么解决这个问题?我们在可以在生成代理类的同时,调用一个别人指定给我的处理方式。

在代理里面调用方法的时候,方法前面加什么(比如:日志),后面加什么,不写死,由别人动态指定。方法的执行交给别人了执行,而执行的过程,可以由我们自己来定(多态)。

思路:将大问题分解为小问题

第一步:需要一个可以动态指定对某一方法进行处理的东西 (InvocationHandler 接口,方法调用处理器)

第二步:TimeHandler

代理模式-动态代理 修改成可以任意修改代理逻辑

一、概述

1.目标:动态代理的代理逻辑可以任意修改

2.思路:

(1)要把代理逻辑抽离,站在jvm的角度思考,应独立出InvocationHandler接口,并接收被代理的对象及方法作为参数invoke(Object o, Method m),并本身作为参数传给newProxyInstance(Class interfze,InvocationHandler handler) 

(2)InvocationHandler本身聚合被代理类target,以便在target的方法前后增加代理逻辑

3.知识点:

(1)按名字找方法java.lang.reflect.Method md = proxy.Movable.class.getMethod("stop");

(2)按"."拆分字符串:String [] parts = m.toString().replace("abstract ", "").split("\\.");

 
 

二、代码

1.InvocationHandler.java

2.TimeHandler.java

3.Movable.java

4.Tank.java

5.Proxy.java

6.Client.java

 
 

1.InvocationHandler.java

  1. package com.weiqinshian.proxy;
  2. import java.lang.reflect.Method;
  3. public
    interface InvocationHandler
  4. {
  5.    public
    void invoke(Object o, Method m);
  6. }

2.TimeHandler.java

  1. package com.weiqinshian.proxy;
  2. import java.lang.reflect.Method;
  3. public
    class TimeHandler implements InvocationHandler
  4. {
  5.    // 保留被代理的对象
  6.    private Object target;
  7.    public TimeHandler(Object target)
  8.    {
  9.       this.target = target;
  10.    }
  11.    public
    void invoke(Object o, Method m)
  12.    {
  13.       System.out.println("Time Proxy start...........");
  14.       long start = System.currentTimeMillis();
  15.       try
  16.       {
  17.          // 除了静态方法,方法的调用都要先已知对象,所以要把对象o作为参数传进去
  18.          m.invoke(target);
  19.       } catch (Exception e)
  20.       {
  21.          e.printStackTrace();
  22.       }
  23.       long end = System.currentTimeMillis();
  24.       System.out.println("花费时间:" + (end - start));
  25.       System.out.println("Time Proxy end...........");
  26.    }
  27. }

 

3.Moveable.java

  1. package com.weiqinshian.proxy;
  2.  
  3. public
    interface Moveable
  4. {
  5.    public
    void move();
  6.    public
    void stop();
  7. }

 

4.Tank.java

  1. package com.weiqinshian.proxy;
  2.  
  3. import java.util.Random;
  4.  
  5. public
    class Tank implements Moveable
  6. {
  7.  
  8.    @Override
  9.    public
    void move()
  10.    {
  11.       System.out.println("tank move........");
  12.       try
  13.       {
  14.          Thread.sleep(new Random().nextInt(10000));
  15.       } catch (InterruptedException e)
  16.       {
  17.          e.printStackTrace();
  18.       }
  19.  
  20.    }
  21.  
  22.    public
    void stop()
  23.    {
  24.       System.out.println("Tank stopping.......");
  25.  
  26.    }
  27. }

 
 

5.Proxy.java

  1. package com.weiqinshian.proxy;
  2.  
  3. import java.io.File;
  4. import java.io.FileWriter;
  5. import java.lang.reflect.Constructor;
  6. import java.lang.reflect.Method;
  7. import java.net.URL;
  8. import java.net.URLClassLoader;
  9.  
  10. import javax.tools.JavaCompiler;
  11. import javax.tools.StandardJavaFileManager;
  12. import javax.tools.ToolProvider;
  13. import javax.tools.JavaCompiler.CompilationTask;
  14.  
  15. public
    class Proxy
  16. {
  17.  
  18.    public
    static Object newProxyInstance(Class interfze, InvocationHandler handler) throws Exception
  19.    {
  20.       String rt = "\n\r";
  21.       // 拼接"实现接口方法"的字符串
  22.       String methodStr = "";
  23.       for (Method m : interfze.getMethods())
  24.       {
  25.          // 取出方法的修饰符和返回值类型
  26.          String[] parts = m.toString().replace("abstract ", "").split("\\.");
  27.          String[] parts2 = parts[0].split("
    ");
  28.  
  29.          methodStr += "@Override" + rt + parts2[0] + "
    " + parts2[1] + "
    " + m.getName() + "() {" + rt + "try{" + rt + "java.lang.reflect.Method md = " + interfze.getName() + ".class.getMethod(\""
  30.                + m.getName() + "\");" + rt +
  31.                // 传this进去其实没什么用,invoke实际是调用target的方法m.invoke(target)
  32.                "handler.invoke(this, md);" + rt + "}catch(Exception e){" + rt + " e.printStackTrace();" + rt + "}" + rt + "}" + rt;
  33.       }
  34.       // 动态代理文件的源码
  35.       String str = " package com.weiqinshian.proxy; " + rt +
  36.  
  37.       "public class TankTimeProxy implements " + interfze.getName() + " {" + rt +
  38.  
  39.       // 聚合Handler
  40.             "private InvocationHandler handler;" + rt +
  41.  
  42.             "public TankTimeProxy(InvocationHandler handler) {" + rt + "this.handler = handler;" + rt + "}" + rt + methodStr + rt + "}";
  43.  
  44.       // 把源码写到java文件里
  45.       File file = new File("d:/src/com/weiqinshian/proxy/TankTimeProxy.java");
  46.       FileWriter fw = new FileWriter(file);
  47.       fw.write(str);
  48.       fw.flush();
  49.       fw.close();
  50.  
  51.       // 编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误
  52.       JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
  53.  
  54.       // 文件管事器
  55.       StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);
  56.  
  57.       // 编译单元
  58.       Iterable units = fileMgr.getJavaFileObjects(file);
  59.  
  60.       // 编译任务
  61.       CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);
  62.  
  63.       // 编译
  64.       t.call();
  65.       fileMgr.close();
  66.  
  67.       // 把类load到内存里src\com\weiqinshian\proxy
  68.       URL[] urls = new URL[]
  69.       { new URL("file:/" + "d:/src/") };
  70.       System.out.println("file:/" + System.getProperty("user.dir") + "/src/com/weiqinshian/proxy/TankTimeProxy.class");
  71.       URLClassLoader uc = new URLClassLoader(urls);
  72.       Class c = uc.loadClass("com.weiqinshian.proxy.TankTimeProxy");
  73.  
  74.       // 生成实例
  75.       // return c.newInstance();
  76.       // //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
  77.       // Constructor ctr = c.getConstructor(interfze);
  78.       Constructor ctr = c.getConstructor(InvocationHandler.class);
  79.       return ctr.newInstance(handler);
  80.  
  81.    }
  82. }

 6.Client.java

作为客户来讲,调用这个方法的时候传了接口,我就知道方法返回的对象是实现了那个接口的,所以,强制转换为接口,这个肯定是没有什么问题的,往里面传new timeHandler,我自己要做什么样的代理的实现是由我自己来决定的

  1. package com.weiqinshian.proxy;
  2. public
    class Client
  3. {
  4.    public
    static
    void main(String[] args) throws Exception
  5.    {
  6.       Moveable m = (Moveable) Proxy.newProxyInstance(Moveable.class, new TimeHandler(new Tank()));//
  7.       m.move();
  8.       m.stop();
  9.    }
  10. }

 
 

三、运行结果

 

四、动态生成代码

  1. package com.weiqinshian.proxy;
  2. import java.lang.reflect.InvocationHandler;
  3. public
    class TankTimeProxy implements com.weiqinshian.proxy.Moveable {
  4.     private InvocationHandler handler;
  5.     public TankTimeProxy(InvocationHandler handler) {
  6.         this.handler = handler;
  7.     }
  8.     @Override
  9.     public
    void stop() {
  10.         try {
  11.             java.lang.reflect.Method md = com.weiqinshian.proxy.Moveable.class.getMethod("stop");
  12.             handler.invoke(this, md);
  13.         } catch (Exception e) {
  14.             e.printStackTrace();
  15.         }
  16.     }
  17.     @Override
  18.     public
    void move() {
  19.         try {
  20.             java.lang.reflect.Method md = com.weiqinshian.proxy.Moveable.class.getMethod("move");
  21.             handler.invoke(this, md);
  22.         } catch (Exception e) {
  23.             e.printStackTrace();
  24.         }
  25.     }
  26. }

CGLIB 和ASM 可以直接修改二进制码实现动态代理

 

CGLIB(Code Generation Library)是一个开源项目!

是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。

 

ASM 是一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。

 

Java-马士兵动态代理模式的更多相关文章

  1. Java设计模式—Proxy动态代理模式

    代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代 ...

  2. java学习之动态代理模式

    package com.gh.dynaproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Metho ...

  3. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  4. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  5. Java静态代理与动态代理模式的实现

    前言:    在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总找不到时间去找他,他也没办法.后来,房东想了一个办法,他找到 ...

  6. java jdk动态代理模式举例浅析

    代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...

  7. Java的三种代理模式(Spring动态代理对象)

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

  8. Java 代理模式(二) Java中的动态代理

    动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Objec ...

  9. 关于java动态代理模式

    1. 动态代理 动态代理就是通过代理类是代理类与相关接口不直接发生联系,而在运行期(Runtime)实现动态关联. 动态代理主要用到java.lang.reflect包中的两个类,Invocation ...

随机推荐

  1. 各大安卓应用市场APP上传提交与收录

    360 提交网址 应用宝 提交网址 百度 提交网址 91 提交网址 安卓 提交网址 PP助手 提交网址 小米 提交网址 华为 提交网址 OPPO 提交网址 魅族 提交网址 乐视 提交网址 豌豆荚 提交 ...

  2. JS判断是否是微信页面,判断手机操作系统(ios或android)并跳转到不同下载页面

    JS判断客户端是否是iOS或者Android 参考:http://caibaojian.com/browser-ios-or-android.html function is_weixin() { v ...

  3. Vim 键盘指令高清图

    个人感觉挺好用的 推荐大家使用windows版的vim,个人用着感觉不错,在linux上用惯了vim的朋友可以试试这个.

  4. hive的数据导出方式

    hive有三种导出数据的方式 >导出数据到本地 >导出数据到hdfs >导出数据到另一个表   导出数据到本地文件系统 insert overwrite local director ...

  5. Jetty使用教程(四:24-27)—Jetty开发指南

    二十四.处理器(Handler ) 24.1 编写一个常用的Handler Jetty的Handler组件用来处理接收到的请求. 很多使用者不需要编写Jetty的Handler ,而是通过使用Serv ...

  6. js 数据类型问题

    1. alert(type of 变量名) console.log(type of 变量名); 可以答应数据类型 2.var cost_price=parseFloat(parseFloat($(&q ...

  7. OneThink开发框架

    OneThink是一个开源的内容管理框架,基于最新的ThinkPHP3.2版本开发,提供更方便.更安全的WEB应用开发体验,采用了全新的架构设计和命名空间机制,融合了模块化.驱动化和插件化的设计理念于 ...

  8. html学习第二天—— 第七章——CSS样式基本知识

    外部式css样式,写在单独的一个文件中外部式css样式(也可称为外联式)就是把css代码写一个单独的外部文件中,这个css样式文件以“.css”为扩展名,在<head>内(不是在<s ...

  9. 弹性盒子布局flexbox

    弹性盒子display:flexbox一般应用于父元素的容器上,然后对子元素来进行弹性布局 设置了flexbox的父元素不能设置具体的宽度与高度的值,而是通过子元素来设置值,父元素弹性的包裹既可 相关 ...

  10. 2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree

    Magic boy Bi Luo with his excited tree Problem Description Bi Luo is a magic boy, he also has a migi ...