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 }

三、运行结果

时间: 2024-10-05 05:02:21

Java 动态代理 修改成可以代理任意接口的相关文章

hadoop21---使用代理修改List,代理流程

package cn.itcast_05_proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; public class ListDemo { @SuppressWarnings({ "rawtypes", &

Java 动态代理 修改成可以任意修改代理逻辑

一.概述 1.目标:动态代理的代理逻辑可以任意修改 2.思路: (1)要把代理逻辑抽离,站在jvm的角度思考,应独立出InvocationHandler接口,并接收被代理的对象及方法作为参数invoke(Object o, Method m),并本身作为参数传给newProxyInstance(Class interfze,InvocationHandler handler) (2)InvocationHandler本身聚合被代理类target,以便在target的方法前后增加代理逻辑 3.知识

Bash终端命令行,使用privoxy将socks代理转成http代理

安装privoxy # Ubuntu/debian sudo apt-get install privoxy # Centos sudo yum install privoxy # Mac osx sudo port install privoxy 修改配置文件 vi /etc/privoxy/config # HTTP parent looks like this: # forward-socks4 / 127.0.0.1:1080 . # # To chain Privoxy and Tor

jdk动态代理与cglib代理、spring aop代理实现原理解析

原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 动态代理实现主要有2种形式,主要分为: 1.jdk动态代理: 1)原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理,位于java.lang.reflect包下) 2)实现方式: 1. 通过实现Invocati

Java动态数组

其中java动态数组: Java动态数组是一种可以任意伸缩数组长度的对象,在Java中比较常用的是ArrayList,ArrayList是javaAPI中自带的java.util.ArrayList.下面介绍一下ArrayList作为Java动态数组的用法. 1.语法:add()是添加一个新的元素,remove()删除一个元素,size()获得ArrayList的长度.ArrayList的下标是从0开始. 2.示例代码 [java] view plaincopy package wang48.j

java动态代理(JDK和cglib)

转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,

《转》java动态代理(JDK和cglib)

该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建

《转》JAVA动态代理(JDK和CGLIB)

该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建

(转)java动态代理(JDK和cglib)

博文转自http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期