【Java基础】代理 - Proxy
来源:互联网 发布:mac如何删除qq浏览器 编辑:程序博客网 时间:2024/06/05 19:58
利用代理可以在运行时创建一个实现了一组给定接口的新类。这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用。
代理类是在程序运行过程中创建的。然而,一旦被创建,就变成了常规类,与虚拟机中的任何其他类没有什么区别。
对于特定的类加载器和预设的一组接口来说,只能有一个代理类。也就是说,如果使用同一个类加载器和接口数组调用两次newProxyInstance方法的话,只能够得到同一个类的两个对象。
代理实际上就是java.lang.reflect.Proxy动态地根据所指定的接口生成的class byte。该类会继承Proxy类,并实现所有指定的接口(interfaces参数),最后使用参入的class loader将class byte加载如系统,生成这样的一个类的对象。
在最后的一个示例中,可以看到生成的代理类的继承体系及实现的接口。
代理类 - Proxy
public class Proxy extends Object implements Serializable (java.lang.reflect)
要想创建一个代理对象,需要使用Proxy类的newProxyInstance方法,这个方法有三个参数:
static Object
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
- 一个类加载器:作为Java安全模型的一部分,对于系统类和从因特网上下载来的类,可以使用不同的类加载器。使用null表示使用默认的类加载器(系统类的加载器)。
- 一个Class对象数组,每个元素都是需要实现的接口。
- 一个调用处理器。
调用处理器 - InvocationHandler
public interface InvocationHandler (java.lang.reflect)
Object
invoke(Object proxy, Method method, Object[] args)
Processes a method invocation on a proxy instance and returns the result.
该方法定义了代理对象调用方法时希望执行的动作。当调用代理类时,代理类只会调用InvocationHandler的invoke方法,所以真正实现的方法必须在invoke方法中去调用。
示例
系统接口代理
Integer类实现了Comparable接口。
import java.util.*;import java.lang.reflect.*;public class ProxyTest { public static void main(String[] args){ Object[] elements = new Object[100]; // fill elements with proxies for the integer for (int i = 0; i < elements.length; i++){ Integer value = i + 1; Class[] interfaces = value.getClass().getInterfaces(); InvocationHandler handler = new TraceHandler(value); Object proxy = Proxy.newProxyInstance(null, interfaces, handler); elements[i] = proxy; } // construct a random integer Integer key = new Random().nextInt(elements.length) + 1; // search for the key int result = Arrays.binarySearch(elements, key); if (result >= 0){ System.out.println(elements[result]); } }}class TraceHandler implements InvocationHandler{private Object target;public TraceHandler(Object t){target = t;}public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {// print the invoked method infoSystem.out.print("Proxy invoke: ");System.out.print(target);System.out.print("." + m.getName() + "(");if (args != null){for (int i = 0; i < args.length; i++){System.out.print(args[i]);if (i < args.length - 1){System.out.print(", ");}}}System.out.println(")");// invoke actual methodreturn m.invoke(target, args);}}
自定义接口代理
import java.util.*;import java.lang.reflect.*;public class ProxyTest2 { public static void main(String[] args){ TestClass testClass = new TestClass(); Class[] interfaces = testClass.getClass().getInterfaces(); InvocationHandler handler = new TraceHandler2(testClass); Object proxy = Proxy.newProxyInstance(testClass.getClass().getClassLoader(), interfaces, handler); ((TestInterface)proxy).test(); //((TestClass)proxy).test(); error; Proxy cannot be cast to TestClass //((TestClass)proxy).test2(); error; Proxy cannot be cast to TestClass }}interface TestInterface{void test();}class TestClass implements TestInterface{ public void test(){ System.out.println("TestClass.test"); } public void test2(){ System.out.println("TestClass.test2"); } public String toString(){ return "TestClass Instance"; }}class TraceHandler2 implements InvocationHandler{private Object target;public TraceHandler2(Object t){target = t;}public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {// print the invoked method infoSystem.out.print("Proxy invoke: ");System.out.print(target);System.out.print("." + m.getName() + "(");if (args != null){for (int i = 0; i < args.length; i++){System.out.print(args[i]);if (i < args.length - 1){System.out.print(", ");}}}System.out.println(")");// invoke actual methodreturn m.invoke(target, args);}}
打印代理类
我们使用反射中的打印类信息的方法,查看上面示例中生成的代理类的定义:
public class ReflectionTest{public static void main(String[] args){ TestClass testClass = new TestClass(); Class[] interfaces = testClass.getClass().getInterfaces(); InvocationHandler handler = new TraceHandler2(testClass); Object proxy = Proxy.newProxyInstance(testClass.getClass().getClassLoader(), interfaces, handler); ClassAnalyzer.printClass(proxy.getClass());}}
输出:
0 0
- 【Java基础】代理 - Proxy
- Java基础---Proxy 代理
- java基础进阶-------代理(Proxy)
- Java基础之代理Proxy
- java基础总结32-代理(Proxy)
- java Proxy代理&cglib代理
- Java基础加强总结(三)——代理(Proxy)
- Java基础加强总结(三)——代理(Proxy)
- Java基础加强总结——代理(Proxy)
- Java基础加强总结——代理(Proxy)
- Java基础加强总结(三)——代理(Proxy)
- Java基础加强总结之动态代理(Proxy)
- Java基础学习总结——动态代理技术(Proxy)
- java 代理(proxy)模式
- Java Proxy动态代理
- java Proxy 代理模式
- JAVA实现代理proxy
- Java 动态代理 Proxy
- 前端开发神器sublime+emmet
- C++第一次作业
- SQL编程实例:SQL数据库,存储过程+事务处理+回滚+数据迁移
- linux内核锁机制实例代码-不可睡眠锁之自旋锁之二
- VS2010环境下OpenCV&OpenGL配置
- 【Java基础】代理 - Proxy
- Filter二(利用Filter实现简单的登录验证)
- onInterceptTouchEvent和onTouchEvent举例分析
- Android--侧滑菜单应用的实现
- OnTouchListener事件监听实现方式之GestureDetector
- erlang 语法练习
- 开放Java Servlet需要的Jar包
- select into from 与 insert into select 区别鉴赏
- 比较简单 就到这了