, 以前一直没觉得,现在发现写博客还是一件蛮有趣的事情, :)
动态代理的实现有两种方式: 一种是jdk的动态代理,实现类必须实现某个接口; 另一种是cglib,使用底层的字节码技术,对实现类没有要求。
首先来看一个简单使用jdk动态代理的例子:
第一步: 定义接口
public interface Animal { public String getName(); }
第二步:具体实现类
public class Dog implements Animal { @Override public String getName() { System.out.println("***pretty dog***"); return "Dog"; } }
第三步:实现代理类,代理类需要实现InvocationHandler接口
public class ProxyTest implements InvocationHandler { private Animal animal; public ProxyTest(Animal animal) { super(); this.animal = animal; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("---before method---"); Object obj = method.invoke(animal, args); System.out.println("---after method---"); return obj; } public static void main(String[] args) { Animal animal = new Dog(); ClassLoader classLoader = animal.getClass().getClassLoader(); Class<?>[] interfaces = animal.getClass().getInterfaces(); InvocationHandler h = new ProxyTest(animal); Animal proxyAnimal = (Animal) Proxy.newProxyInstance(classLoader, interfaces, h); proxyAnimal.getName(); } }
运行上面的代码,输出结果如下:
---before method---
***pretty dog***
---after method---
下面来看下代码的调用过程,在main方法中,调用Proxy.newProxyInstance方法来生成代理对象,code如下:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw new NullPointerException(); } /* * Look up or generate the designated proxy class. */ Class cl = getProxyClass(loader, interfaces); /* * Invoke its constructor with the designated invocation handler. */ try { Constructor cons = cl.getConstructor(constructorParams); return (Object) cons.newInstance(new Object[] { h }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { throw new InternalError(e.toString()); } catch (InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { throw new InternalError(e.toString()); } }
在newProxyInstance方法中,通过调用getProxyClass方法来获取代理类的class对象,主要代码如下(原方法较长,只是选择了部分关键的code):
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException { Map cache; /* * 如果已经创建或者正在创建代理对象,则直接返回或者等待创建完成;否则跳出循环 */ synchronized (cache) { do { Object value = cache.get(key); if (value instanceof Reference) { proxyClass = (Class) ((Reference) value).get(); } if (proxyClass != null) { // proxy class already generated: return it return proxyClass; } else if (value == pendingGenerationMarker) { // proxy class being generated: wait for it try { cache.wait(); } catch (InterruptedException e) { /* * The class generation that we are waiting for should * take a small, bounded time, so we can safely ignore * thread interrupts here. */ } continue; } else { /* * No proxy class for this list of interfaces has been * generated or is being generated, so we will go and * generate it now. Mark it as pending generation. */ cache.put(key, pendingGenerationMarker); break; } } while (true); } byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces); try { proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { } return proxyClass; }
ProxyGenerator在rt.jar中,需要先下载源码,我是直接使用eclipse 的反编译工具来看。可以参考链接: http://tangmingjie2009.iteye.com/blog/1916992。
最终生成的代理类经反编译之后如下(下面的文件是直接通过调用byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy1", animal.getClass().getInterfaces()) 生成):
public final class $Proxy1 extends Proxy implements Animal { public $Proxy1(InvocationHandler invocationhandler) { super(invocationhandler); } public final String getName() { try { return (String)super.h.invoke(this, m3, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final boolean equals(Object obj) { try { return ((Boolean)super.h.invoke(this, m1, new Object[] { obj })).booleanValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)super.h.invoke(this, m0, null)).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)super.h.invoke(this, m2, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } private static Method m3; private static Method m1; private static Method m0; private static Method m2; static { try { m3 = Class.forName("ss.proxy.Animal").getMethod("getName", new Class[0]); 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]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); } catch(NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexception.getMessage()); } catch(ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexception.getMessage()); } } }
因此当调用ProxyTest中的getName的方法时,会调用$Proxy1对象的getName方法,然后通过super.h.invoke(this, m3, null)调用ProxyTest的invoke方法,其中参数m3为Dog的getName方法。
相关推荐
JDK动态代理,关于jdk动态代理的问题!详细的说明!JDK动态代理JDK动态代理
对jdk中的动态代理执行过程进行了详细跟踪,并反编译了动态代理调用自动生成的代理类,并对其进行了详细讲解。
jdk 的动态代理和CGLIB代理
JDK动态代理源码下载,动态产生代理,实现对【不同类】,【不同方法】的代理
jdk动态代理技术详解,可以学习一下,不错的
java jdk 动态代理 演示demo
动态代理是使用jdk的反射机制,创建对象的能力, 创建的是代理类的对象。 而不用你创建类文件。不用写java文件。 动态:在程序执行时,调用jdk提供的方法才能创建代理类的对象。jdk动态代理,必须有接口,目标类必须...
Jdk动态代理,基于接口的代理示例 InovactionHandler Proxy
通过一个简单例子来理解JDK动态代理的思想,资源为拷贝的视频讲解的内容。
NULL 博文链接:https://jummy.iteye.com/blog/255628
AOP之JDK动态代理和CGLib动态代理 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45195383
模拟JDK动态代理内部实现
spring aop jdk 动态代理的底层实现解析模拟
java代理机制 JDK动态代理和cglib代理 详解
JDK动态代理proxy的基本工作原理代码!!
java静态代理 jdk动态代理 cglib动态代理 代理原理
java jdk 动态代理演示demo
基于java的jdk动态代理, 比较了静态代理与动态代理的区别,以及动态代理的底层实现,反编译class文件 jdk动态代理和cglib的区别
JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)
* * * * JDK动态代理 JDK动态代理 JDK动态代理是通过java.lang.reflect.Proxy 类来实现的,我们可以调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现...