JDK动态代理步骤详解(源码分析)
动态代理步骤
1.创建一个实现接口invocationhandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过proxy的静态方法
通过proxy的静态方法
proxyobject proxyobject = new proxyobject(); invocationhandler invocationhandler = new dynamicproxy(proxyobject); classloader classloader = proxyobject.getclass().getclassloader(); proxyobjectinterface proxy = (iroom) proxy.newproxyinstance(classloader,new class[] {proxyobjectinterface.class},invocationhandler); proxy.execute(); public class dynamicproxy implements invocationhandler { private object object; public dynamicproxy(object object){ this.object = object; } @override public object invoke(object proxy, method method, object[] args) throws throwable { object result = method.invoke(object,args); return result; } }
创建一个代理 newproxyinstance
public static object newproxyinstance(classloader loader, class<?>[] interfaces, invocationhandler h) throws illegalargumentexception { //检验h不为空,h为空抛异常 objects.requirenonnull(h); //接口的类对象拷贝一份 final class<?>[] intfs = interfaces.clone(); //进行一些安全性检查 final securitymanager sm = system.getsecuritymanager(); if (sm != null) { checkproxyaccess(reflection.getcallerclass(), loader, intfs); } /* * look up or generate the designated proxy class. * 查询(在缓存中已经有)或生成指定的代理类的class对象。 */ class<?> cl = getproxyclass0(loader, intfs); /* * invoke its constructor with the designated invocation handler. */ try { if (sm != null) { checknewproxypermission(reflection.getcallerclass(), cl); } //得到代理类对象的构造函数,这个构造函数的参数由constructorparams指定 //参数constructorparames为常量值: private static final class<?>[] constructorparams = { invocationhandler.class }; final constructor<?> cons = cl.getconstructor(constructorparams); final invocationhandler ih = h; if (!modifier.ispublic(cl.getmodifiers())) { accesscontroller.doprivileged(new privilegedaction<void>() { public void run() { cons.setaccessible(true); return null; } }); } //这里生成代理对象,传入的参数new object[]{h}后面讲 return cons.newinstance(new object[]{h}); } catch (illegalaccessexception|instantiationexception e) { throw new internalerror(e.tostring(), e); } catch (invocationtargetexception e) { throwable t = e.getcause(); if (t instanceof runtimeexception) { throw (runtimeexception) t; } else { throw new internalerror(t.tostring(), t); } } catch (nosuchmethodexception e) { throw new internalerror(e.tostring(), e); } }
先对h进行判空处理。
这段代码核心就是通过getproxyclass0(loader, intfs)得到代理类的class对象,然后通过class对象得到构造方法,进而创建代理对象。下一步看getproxyclass0这个方法。从1可知,先接口得到接口类,当接口的数量超过65535,则报异常。
//此方法也是proxy类下的方法 private static class<?> getproxyclass0(classloader loader, class<?>... interfaces) { if (interfaces.length > 65535) { throw new illegalargumentexception("interface limit exceeded"); } // if the proxy class defined by the given loader implementing // the given interfaces exists, this will simply return the cached copy; // otherwise, it will create the proxy class via the proxyclassfactory //意思是:如果代理类被指定的类加载器loader定义了,并实现了给定的接口interfaces, //那么就返回缓存的代理类对象,否则使用proxyclassfactory创建代理类。 return proxyclasscache.get(loader, interfaces); }
proxyclasscache 是一个弱引用的缓存
这里看到proxyclasscache,有cache便知道是缓存的意思,正好呼应了前面look up or generate the designated proxy class。查询(在缓存中已经有)或生成指定的代理类的class对象这段注释。
在进入get方法之前,我们看下 proxyclasscache是什么?高能预警,前方代码看起来可能有乱,但我们只需要关注重点即可。
private static final weakcache<classloader, class<?>[], class<?>> proxyclasscache = new weakcache<>(new keyfactory(), new proxyclassfactory()); //k代表key的类型,p代表参数的类型,v代表value的类型。 // weakcache<classloader, class<?>[], class<?>> proxyclasscache 说明proxyclasscache存的值是class<?>对象,正是我们需要的代理类对象。 final class weakcache<k, p, v> { private final referencequeue<k> refqueue = new referencequeue<>(); // the key type is object for supporting null key private final concurrentmap<object, concurrentmap<object, supplier<v>>> map = new concurrenthashmap<>(); private final concurrentmap<supplier<v>, boolean> reversemap = new concurrenthashmap<>(); private final bifunction<k, p, ?> subkeyfactory; private final bifunction<k, p, v> valuefactory; public weakcache(bifunction<k, p, ?> subkeyfactory, bifunction<k, p, v> valuefactory) { this.subkeyfactory = objects.requirenonnull(subkeyfactory); this.valuefactory = objects.requirenonnull(valuefactory); }
其中map变量是实现缓存的核心变量,他是一个双重的map结构: (key, sub-key) -> value。其中key是传进来的classloader进行包装后的对象,sub-key是由weakcache构造函数传人的keyfactory()生成的。value就是产生代理类的对象,是由weakcache构造函数传人的proxyclassfactory()生成的。如下,回顾一下:
proxyclasscache是个weakcache类的对象,调用proxyclasscache.get(loader, interfaces); 可以得到缓存的代理类或创建代理类(没有缓存的情况)。
说明weakcache中有get这个方法。先看下weakcache类的定义(这里先只给出变量的定义和构造函数),继续看它的get();
//k和p就是weakcache定义中的泛型,key是类加载器,parameter是接口类数组 public v get(k key, p parameter) { //检查parameter不为空 objects.requirenonnull(parameter); //清除无效的缓存 expungestaleentries(); // cachekey就是(key, sub-key) -> value里的一级key, object cachekey = cachekey.valueof(key, refqueue); // lazily install the 2nd level valuesmap for the particular cachekey //根据一级key得到 concurrentmap<object, supplier<v>>对象。如果之前不存在,则新建一个concurrentmap<object, supplier<v>>和cachekey(一级key)一起放到map中。 concurrentmap<object, supplier<v>> valuesmap = map.get(cachekey); if (valuesmap == null) { concurrentmap<object, supplier<v>> oldvaluesmap = map.putifabsent(cachekey, valuesmap = new concurrenthashmap<>()); if (oldvaluesmap != null) { valuesmap = oldvaluesmap; } } // create subkey and retrieve the possible supplier<v> stored by that // subkey from valuesmap //这部分就是调用生成sub-key的代码,上面我们已经看过怎么生成的了 object subkey = objects.requirenonnull(subkeyfactory.apply(key, parameter)); //通过sub-key得到supplier supplier<v> supplier = valuesmap.get(subkey); //supplier实际上就是这个factory factory factory = null; while (true) { //如果缓存里有supplier ,那就直接通过get方法,得到代理类对象,返回,就结束了,一会儿分析get方法。 if (supplier != null) { // supplier might be a factory or a cachevalue<v> instance v value = supplier.get(); if (value != null) { return value; } } // else no supplier in cache // or a supplier that returned null (could be a cleared cachevalue // or a factory that wasn't successful in installing the cachevalue) // lazily construct a factory //下面的所有代码目的就是:如果缓存中没有supplier,则创建一个factory对象,把factory对象在多线程的环境下安全的赋给supplier。 //因为是在while(true)中,赋值成功后又回到上面去调get方法,返回才结束。 if (factory == null) { factory = new factory(key, parameter, subkey, valuesmap); } if (supplier == null) { supplier = valuesmap.putifabsent(subkey, factory); if (supplier == null) { // successfully installed factory supplier = factory; } // else retry with winning supplier } else { if (valuesmap.replace(subkey, supplier, factory)) { // successfully replaced // cleared cacheentry / unsuccessful factory // with our factory supplier = factory; } else { // retry with current supplier supplier = valuesmap.get(subkey); } } } }
所以接下来我们看factory类中的get方法。接下来看supplier的get()
public synchronized v get() { // serialize access // re-check supplier<v> supplier = valuesmap.get(subkey); //重新检查得到的supplier是不是当前对象 if (supplier != this) { // something changed while we were waiting: // might be that we were replaced by a cachevalue // or were removed because of failure -> // return null to signal weakcache.get() to retry // the loop return null; } // else still us (supplier == this) // create new value v value = null; try { //代理类就是在这个位置调用valuefactory生成的 //valuefactory就是我们传入的 new proxyclassfactory() //一会我们分析proxyclassfactory()的apply方法 value = objects.requirenonnull(valuefactory.apply(key, parameter)); } finally { if (value == null) { // remove us on failure valuesmap.remove(subkey, this); } } // the only path to reach here is with non-null value assert value != null; // wrap value with cachevalue (weakreference) //把value包装成弱引用 cachevalue<v> cachevalue = new cachevalue<>(value); // put into reversemap // reversemap是用来实现缓存的有效性 reversemap.put(cachevalue, boolean.true); // try replacing us with cachevalue (this should always succeed) if (!valuesmap.replace(subkey, this, cachevalue)) { throw new assertionerror("should not reach here"); } // successfully replaced us with new cachevalue -> return the value // wrapped by it return value; } }
拨云见日,来到proxyclassfactory的apply方法,代理类就是在这里生成的。
首先看proxyclasscache的定义weakcache<classloader, class<?>[], class<?>>,泛型里面第一个表示加载器k,第二个表示接口类p,第三个则是生成的代理类v。而v的生成则是通过proxyclassfactory生成的。调用其apply();
//这里的bifunction<t, u, r>是个函数式接口,可以理解为用t,u两种类型做参数,得到r类型的返回值 private static final class proxyclassfactory implements bifunction<classloader, class<?>[], class<?>> { // prefix for all proxy class names //所有代理类名字的前缀 private static final string proxyclassnameprefix = "$proxy"; // next number to use for generation of unique proxy class names //用于生成代理类名字的计数器 private static final atomiclong nextuniquenumber = new atomiclong(); @override public class<?> apply(classloader loader, class<?>[] interfaces) { map<class<?>, boolean> interfaceset = new identityhashmap<>(interfaces.length); //验证代理接口,可不看 for (class<?> intf : interfaces) { /* * verify that the class loader resolves the name of this * interface to the same class object. */ class<?> interfaceclass = null; try { interfaceclass = class.forname(intf.getname(), false, loader); } catch (classnotfoundexception e) { } if (interfaceclass != intf) { throw new illegalargumentexception( intf + " is not visible from class loader"); } /* * verify that the class object actually represents an * interface. */ if (!interfaceclass.isinterface()) { throw new illegalargumentexception( interfaceclass.getname() + " is not an interface"); } /* * verify that this interface is not a duplicate. */ if (interfaceset.put(interfaceclass, boolean.true) != null) { throw new illegalargumentexception( "repeated interface: " + interfaceclass.getname()); } } //生成的代理类的包名 string proxypkg = null; // package to define proxy class in //代理类访问控制符: public ,final int accessflags = modifier.public | modifier.final; /* * record the package of a non-public proxy interface so that the * proxy class will be defined in the same package. verify that * all non-public proxy interfaces are in the same package. */ //验证所有非公共的接口在同一个包内;公共的就无需处理 //生成包名和类名的逻辑,包名默认是com.sun.proxy, // 类名默认是$proxy 加上一个自增的整数值 //如果被代理类是 non-public proxy interface ,则用和被代理类接口一样的包名 for (class<?> intf : interfaces) { int flags = intf.getmodifiers(); if (!modifier.ispublic(flags)) { accessflags = modifier.final; string name = intf.getname(); int n = name.lastindexof('.'); string pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxypkg == null) { proxypkg = pkg; } else if (!pkg.equals(proxypkg)) { throw new illegalargumentexception( "non-public interfaces from different packages"); } } } if (proxypkg == null) { // if no non-public proxy interfaces, use com.sun.proxy package proxypkg = reflectutil.proxy_package + "."; } /* * choose a name for the proxy class to generate. */ long num = nextuniquenumber.getandincrement(); //代理类的完全限定名,如com.sun.proxy.$proxy0.calss string proxyname = proxypkg + proxyclassnameprefix + num; /* * generate the specified proxy class. */ //核心部分,生成代理类的字节码 byte[] proxyclassfile = proxygenerator.generateproxyclass( proxyname, interfaces, accessflags); try { //把代理类加载到jvm中,至此动态代理过程基本结束了 return defineclass0(loader, proxyname, proxyclassfile, 0, proxyclassfile.length); } catch (classformaterror e) { /* * a classformaterror here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new illegalargumentexception(e.tostring()); } } }
然后调用getmethod(),将equals(),hashcode(),tostring()等方法添加进去。然后遍历所有接口的方法,添加到代理类中。最后将这些方法进行排序。
private static list<method> getmethods(class<?>[] interfaces) { list<method> result = new arraylist<method>(); try { result.add(object.class.getmethod("equals", object.class)); result.add(object.class.getmethod("hashcode", emptyarray.class)); result.add(object.class.getmethod("tostring", emptyarray.class)); } catch (nosuchmethodexception e) { throw new assertionerror(); } getmethodsrecursive(interfaces, result); return result; } private static void getmethodsrecursive(class<?>[] interfaces, list<method> methods) { for (class<?> i : interfaces) { getmethodsrecursive(i.getinterfaces(), methods); collections.addall(methods, i.getdeclaredmethods()); } }
最后输出相关proxy class
package com.zhb.jdk.proxy; import java.io.fileoutputstream; import java.io.ioexception; import java.lang.reflect.proxy; import com.zhb.jdk.dynamicproxy.helloworldimpl; import sun.misc.proxygenerator; /** * @author zhb * @date 2018年8月31日下午11:35:07 * @todo todo */ public class dynamicproxytest { public static void main(string[] args) { iuserservice target = new userserviceimpl(); myinvocationhandler handler = new myinvocationhandler(target); //第一个参数是指定代理类的类加载器(我们传入当前测试类的类加载器) //第二个参数是代理类需要实现的接口(我们传入被代理类实现的接口,这样生成的代理类和被代理类就实现了相同的接口) //第三个参数是invocation handler,用来处理方法的调用。这里传入我们自己实现的handler iuserservice proxyobject = (iuserservice) proxy.newproxyinstance(dynamicproxytest.class.getclassloader(), target.getclass().getinterfaces(), handler); proxyobject.add("陈粒"); string path = "d:/$proxy0.class"; byte[] classfile = proxygenerator.generateproxyclass("$proxy0", helloworldimpl.class.getinterfaces()); fileoutputstream out = null; try { out = new fileoutputstream(path); out.write(classfile); out.flush(); } catch (exception e) { e.printstacktrace(); } finally { try { out.close(); } catch (ioexception e) { e.printstacktrace(); } } } } // decompiled by jad v1.5.8e2. copyright 2001 pavel kouznetsov. // jad home page: http://kpdus.tripod.com/jad.html // decompiler options: packimports(3) fieldsfirst ansi space import com.zhb.jdk.proxy.iuserservice; import java.lang.reflect.*; public final class $proxy0 extends proxy implements iuserservice { private static method m1; private static method m2; private static method m3; private static method m0; //代理类的构造函数,其参数正是是invocationhandler实例, //proxy.newinstance方法就是通过通过这个构造函数来创建代理实例的 public $proxy0(invocationhandler invocationhandler) { super(invocationhandler); } // object类中的三个方法,equals,tostring, hashcode public final boolean equals(object obj) { try { return ((boolean)super.h.invoke(this, m1, new object[] { obj })).booleanvalue(); } catch (error ) { } catch (throwable throwable) { throw new undeclaredthrowableexception(throwable); } } public final string tostring() { try { return (string)super.h.invoke(this, m2, null); } catch (error ) { } catch (throwable throwable) { throw new undeclaredthrowableexception(throwable); } } //接口代理方法 public final void add(string s) { try { // invocation handler的 invoke方法在这里被调用 super.h.invoke(this, m3, new object[] { s }); return; } catch (error ) { } catch (throwable throwable) { throw new undeclaredthrowableexception(throwable); } } public final int hashcode() { try { // 在这里调用了invoke方法。 return ((integer)super.h.invoke(this, m0, null)).intvalue(); } catch (error ) { } catch (throwable throwable) { throw new undeclaredthrowableexception(throwable); } } // 静态代码块对变量进行一些初始化工作 static { try { m1 = class.forname("java.lang.object").getmethod("equals", new class[] { class.forname("java.lang.object") }); m2 = class.forname("java.lang.object").getmethod("tostring", new class[0]); m3 = class.forname("com.zhb.jdk.proxy.iuserservice").getmethod("add", new class[] { class.forname("java.lang.string") }); m0 = class.forname("java.lang.object").getmethod("hashcode", new class[0]); } catch (nosuchmethodexception nosuchmethodexception) { throw new nosuchmethoderror(nosuchmethodexception.getmessage()); } catch (classnotfoundexception classnotfoundexception) { throw new noclassdeffounderror(classnotfoundexception.getmessage()); } } }
以上就是jdk动态代理步骤详解(源码分析)的详细内容,更多关于jdk动态代理的资料请关注其它相关文章!
上一篇: 建议的服务器分区办法