Java-马士兵设计模式学习笔记-代理模式--动态代理 修改成可以代理任意接口

一、概述

1.目标:把Proxy修改成可以代理任意接口及其任意方法

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 proxy;

2 

3 public interface Movable {

4     public void move();

5     public void stop();

6 }

 

2.Tank.java

 1 package proxy;

 2 

 3 import java.util.Random;

 4 

 5 public class Tank implements Movable {

 6 

 7     @Override

 8     public void move() {

 9         System.out.println("Tank moving.......");

10         try {

11             Thread.sleep(new Random().nextInt(2000));

12         } catch (InterruptedException e) {

13             e.printStackTrace();

14         }

15     }

16 

17     @Override

18     public void stop() {

19         System.out.println("Tank stopping.......");

20         

21     }

22 

23 }

 

3.Proxy.java

 1 package 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.JavaCompiler.CompilationTask;

12 import javax.tools.StandardJavaFileManager;

13 import javax.tools.ToolProvider;

14 

15 public class Proxy {

16 

17     public static Object newProxyInstance(Class interfze) throws Exception {

18         

19         String rt = "\n\r";

20         

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 +=

30             "@Override" + rt +

31             parts2[0]+" "+parts2[1]+" "+m.getName()+"() {" + rt +

32                 "System.out.println(\"Time Proxy start...........\");" + rt +

33                 "long start = System.currentTimeMillis();" + rt +

34                 "m." + m.getName() + "();" + rt +

35                 "long end = System.currentTimeMillis();" + rt +

36                 "System.out.println(\"花费时间:\"+(end - start));" + rt +

37                 "System.out.println(\"Time Proxy end...........\");" + rt +

38             "}" ;

39         }

40         

41         

42         //动态代理文件的源码

43         String str = 

44         "package proxy;" + rt +

45 

46         "public class TankTimeProxy implements " + interfze.getName() + " {"+rt+

47 

48             "private " + interfze.getName() + " m;" + rt +

49             

50             "public TankTimeProxy(" + interfze.getName() + " m) {" + rt +

51                 "this.m = m;" + rt +

52             "}" + rt +

53 

54             methodStr + rt +

55 

56         "}" ;

57         

58         //把源码写到java文件里

59         File file = new File(System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.java");

60         FileWriter fw = new FileWriter(file);

61         fw.write(str);

62         fw.flush();

63         fw.close();

64         

65         //编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误

66         JavaCompiler jc = ToolProvider.getSystemJavaCompiler();

67         

68         //文件管事器

69         StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);

70         

71         //编译单元

72         Iterable units = fileMgr.getJavaFileObjects(file);

73         

74         //编译任务

75         CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);

76         

77         //编译

78         t.call();    

79         fileMgr.close();

80         

81         //把类load到内存里

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

83         URLClassLoader uc = new URLClassLoader(urls);

84         Class c = uc.loadClass("proxy.TankTimeProxy");

85         

86         //生成实例

87         //return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错

88         Constructor ctr = c.getConstructor(interfze);

89         return ctr.newInstance(new Tank());

90     }

91 }

 

4.Client.java

 1 package proxy;

 2 

 3 import java.io.IOException;

 4 

 5 import org.junit.Test;

 6 

 7 public class Client {

 8 

 9     @Test

10     public void testProxy() throws Exception{

11         

12         Movable m = (Movable)Proxy.newProxyInstance(Movable.class);

13         m.move();

14         m.stop();

15         

16     }

17 }

 

三、运行结果

Java-马士兵设计模式学习笔记-代理模式--动态代理 修改成可以代理任意接口

你可能感兴趣的:(java)