码迷,mamicode.com
首页 > 编程语言 > 详细

Java 动态代理 修改成可以代理任意接口

时间:2015-06-21 21:02:34      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:

一、概述

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 动态代理 修改成可以代理任意接口

标签:

原文地址:http://www.cnblogs.com/shamgod/p/4592359.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!