-
Java中代理(Proxy)的实现机制5
看TIJ的代理看得有点晕,其中有一段代码如下。(print是包装了下的System.out.println)
package TypeInfo; // typeinfo/SimpleDynamicProxy23.java // TIJ4 Chapter Typeinfo, Exercise 23, page 598 // Inside invoke() in SimpleDynamicProxy.java, try to print the proxy argument and explain // what happens. import java.lang.reflect.*; interface Interface { void doSomething(); void somethingElse(String arg); } class RealObject implements Interface { public void doSomething() { print("doSomething"); } public void somethingElse(String arg) { print("somethingElse " + arg); } } class DynamicProxyHandler implements InvocationHandler { private Object proxied; public DynamicProxyHandler(Object proxied) { this.proxied = proxied; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* * trying to print proxy leads to: * StackOverFlowError * at AbstractStringBuilder.<init>(Unknown Source) * at StringBuilder.<init>(Unknown Source) * at DynamicProxyHandler.invoke(SimpleDynamicProxy23.java) * at $Proxy0.toString(Unknown Source) * at String.valueOf(Unknown Source) * at StrinbBuilcer.append(Unknown Source) * at DynamicProxyHandler.invoke(SimpleDynamicProxy23.java), etc, * probably due to infinite recursion because calls to toString() * are passed repeatedly back to this invoke method */ // System.out.println("proxy: " + proxy); // error System.out.println("**** proxy: " + proxy.getClass() + ", method: " + method + ", args: " + args); if(args != null) for(Object arg : args) System.out.println(" " + args); return method.invoke(proxied, args); } } class SimpleDynamicProxy23 { public static void consumer(Interface iface) { iface.doSomething(); iface.somethingElse("bonobo"); } public static void main(String[] args) { RealObject real = new RealObject(); consumer(real); // Insert a proxy and call again: Interface proxy = (Interface)Proxy.newProxyInstance( Interface.class.getClassLoader(), new Class[]{ Interface.class }, new DynamicProxyHandler(real)); consumer(proxy); } }
代码比较容易看懂,但是其中的内在机制就很隐晦。调试时发现,consumer中调用Interface的方法后程序流直接就跳入了invoke。这是由什么机制决定的?换言之,在consumer中对接口Interface的方法的调用是如何转交给DynamicProxyHandler的invoke方法的?
书中有一句话:“在invoke()内部,在代理上调用方法时需要格外当心,因为对接口的调用将被重定向为对代理的调用。”这句解释了注释掉的“// System.out.println("proxy: " + proxy); // error”的错误是因为引起了无限递归(很空洞的解释,具体怎样引起?)invoke的第一个参数proxy是什么类型?
希望大家不吝赐教。3Q!
2013年6月21日 17:20
4个答案 按时间排序 按投票排序
-
采纳的答案
推荐你看下
http://hllvm.group.iteye.com/group/topic/36843
然后dump出代理类出来 然后观察
我这里给你一份我dump出的package TypeInfo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements Interface { private static Method m1; private static Method m0; private static Method m3; private static Method m4; private static Method m2; public final void doSomething() { try { this.h.invoke(this, m3, null); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final void somethingElse(String paramString) { try { this.h.invoke(this, m4, new Object[] { paramString }); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public $Proxy0(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); } public final int hashCode() { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final boolean equals(Object paramObject) { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() { try { return ((String)this.h.invoke(this, m2, null)); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m3 = Class.forName("TypeInfo.Interface").getMethod("doSomething", new Class[0]); m4 = Class.forName("TypeInfo.Interface").getMethod("somethingElse", new Class[] { Class.forName("java.lang.String") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } }
2013年6月21日 19:02
-
我写过一个博客文章:http://dz.sdut.edu.cn/blog/subaochen/?p=232 简单解释了java动态代理的实现机制,希望能够帮到你。
2013年6月22日 14:44
-
调试时发现,consumer中调用Interface的方法后程序流直接就跳入了invoke。这是由什么机制决定的?
——————
Interface proxy = (Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[]{ Interface.class },
new DynamicProxyHandler(real));
consumer(proxy);
这些代码决定的。
Proxy.newProxyInstance代码是JDK的代码,楼主是想了解JDK的底层实现...?
要了解这个, 就要了解JDK类字节码的生成, 了解了类字节码的生成就要了解类的加载器...
真没必要去纠结JDK的底层实现...如果想了解, 建议去看看《JAVA虚拟机》2013年6月22日 09:25
-
坐等大牛解释,不过invoke的第一个参数proxy应该是被代理的一个实例,就是目标代理类,可以是一个接口的实现或者是一个类的子类...继续
2013年6月21日 17:56
相关推荐
利用JAVA代理Proxy机制实现spring对ibaits的MapperScannerConfigurer功能 详细:http://blog.csdn.net/wq105032007067/article/details/8812598
总结来说,Java动态代理通过`Proxy`和`InvocationHandler`提供了灵活的代码扩展机制,可以在运行时为对象创建代理,实现在不修改原有代码的基础上添加额外功能。这在处理需要拦截和增强的对象时非常有用,例如日志...
在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类是用于创建一个代理对象,而InvocationHandler接口则定义了代理对象调用方法时的行为。 1. **...
在Java动态代理机制中,`Proxy`类是生成代理对象的工厂,而`InvocationHandler`接口定义了代理对象的方法调用处理逻辑。当我们创建一个代理对象时,需要提供一个实现了`InvocationHandler`接口的实例,这个实例将...
### Java 动态代理Proxy应用和底层源码分析 #### 一、Java动态代理简介 Java动态代理是一种在运行时动态生成代理类的技术,通过该技术可以为一个或多个接口生成一个实现类,该实现类可以拦截接口方法的调用,并...
在Java编程中,动态代理是一种强大的机制,它允许我们在运行时创建对象的代理,以便在调用实际方法之前或之后添加额外的行为。本篇将详细探讨Java中的动态代理以及一个常用的第三方库Cglib。 首先,让我们从Java的...
在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。 1. **Proxy类**: `Proxy` 类是Java提供的一个内部类,它主要用于创建一个实现了指定一组接口的...
本文将详细介绍如何在Java中使用IE Proxy代理来实现这一功能。 首先,我们需要理解Java中的网络访问机制。Java使用`java.net`包中的`Socket`和`HttpURLConnection`等类来处理网络通信。当程序运行时,它会使用系统...
在Java中,基于动态代理和反射机制实现ORM可以提高代码的可维护性和灵活性。本篇文章将深入探讨如何在Java环境下,结合MySQL数据库,利用动态代理和反射技术来实现简单的ORM框架。 首先,我们需要了解动态代理和...
总结来说,"proxy.rar"压缩包提供了Java编程中三种代理模式的源代码实例,通过学习这些代码,开发者可以深入理解代理模式的原理和实现,同时掌握泛型在实际项目中的应用。对于提高代码的可扩展性和可维护性,这些都...
总结来说,Java动态代理为开发者提供了灵活的代码扩展机制,可以根据实际需求选择适合的实现方式。JDK动态代理适用于接口丰富的场景,而Cglib更适合对性能有较高要求或者目标对象无法实现接口的情况。
在Java编程中,动态代理是一种强大的机制,它允许我们在运行时创建代理类,这些代理类可以代表或增强原始目标类的行为。动态代理通常用于实现AOP(面向切面编程)或者提供诸如日志、事务管理等跨切面的功能。本文将...
Java代理在编程中是一种强大的设计模式,主要用于在不修改原有对象的...总的来说,Java代理机制在日志记录、性能监控、事务管理等场景中都有广泛的应用,通过代理可以灵活地为对象添加额外的行为,而无需修改原始代码。
在Java中,代理模式可以通过多种方式实现,包括静态代理和动态代理。 在提供的文件列表中,我们可以看到以下几个关键类: 1. `ProxyDisplay`:这个名字暗示了它可能是代理模式中的代理类,用于代表或代替某个实际...
总结,Java Proxy机制是Java中一种强大的工具,它允许我们在运行时动态地创建代理类和对象,从而实现对方法调用的拦截和增强。通过结合`InvocationHandler`,我们可以灵活地添加额外的逻辑,实现AOP编程模式,提升...
在深入探讨Java动态代理的实现过程之前,我们首先需要理解动态代理的基本概念及其在Java中的应用价值。动态代理,顾名思义,是在运行时动态创建代理对象的一种机制,它无需在编译期就确定代理类的具体实现,而是通过...
在Java中实现ProxyServer,通常涉及到Socket编程、多线程以及网络协议的理解。 首先,ProxyServer的核心在于其`serve()`方法,这是处理客户端请求的关键。当客户端发起连接请求时,`serve()`会被调用,它创建一个新...
在Java中实现HTTP代理,通常涉及以下几个核心概念: 1. Socket编程:Java的Socket类提供了低级别的网络通信接口,可以用于建立TCP连接,是实现HTTP代理的基础。通过创建ServerSocket监听客户端连接,然后为每个连接...
总结起来,Java动态代理提供了一种在运行时创建代理对象的机制,通过 `Proxy` 类和 `InvocationHandler` 接口,我们可以灵活地在方法调用前后插入自定义的行为,实现诸如日志、事务等附加功能,极大地增强了代码的可...
Java提供了动态代理机制,主要是通过`java.lang.reflect.Proxy`和`java.lang.reflect.InvocationHandler`接口来实现。动态代理的优点是可以在运行时动态创建代理对象,不需要预先编写代理类。下面是一个动态代理的...