JDK动态代理源码解析
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/80557290 分析版本jdk1.8 在分析jdk动态代理之前,先来了解java WeakReference弱引用的使用。运行期创建目标对象的代理非常耗时,使用缓存来存储生成的代理类显得尤为重要。jdk动态代理使用弱引用指向cache中的代理类,以便代理类对象能够被GC回收。 在java中,当一个对象O被创建时,它被放在Heap里,当GC运行的时候,如果发现没有任何引用指向O,O就会被回收以腾出内存空间,或者说,一个对象被回收,必须满足两个条件:1)没有任何引用指向它;2)GC被运行。在现实情况写代码的时候, 我们往往通过把所有指向某个对象的referece置空来保证这个对象在下次GC运行的时候被回收 (可以用java -verbose:gc来观察gc的行为)。 [java] view plain copy Objectc=newCar(); c=null; 但是, 手动置空对象对于程序员来说, 是一件繁琐且违背自动回收的理念的. 对于简单的情况, 手动置空是不需要程序员来做的, 因为在java中, 对于简单对象, 当调用它的方法执行完毕后, 指向它的引用会被从stack中popup, 所以他就能在下一次GC执行时被回收了. 但是, 也有特殊例外. 当使用cache的时候, 由于cache的对象正是程序运行需要的, 那么只要程序正在运行, cache中的引用就不会被GC给(或者说, cache中的reference拥有了和主程序一样的life cycle). 那么随着cache中的reference越来越多, GC无法回收的object也越来越多, 无法被自动回收. 当这些object需要被回收时, 回收这些object的任务只有交给程序编写者了. 然而这却违背了GC的本质(自动回收可以回收的objects).所以, java中引入了weak reference. 相对于前面举例中的strong reference: [java] view plain copy Objectc=newCar();//只要c还指向carobject,carobject就不会被回收 当一个对象仅仅被weak reference指向, 而没有任何其他strong reference指向的时候, 如果GC运行, 那么这个对象就会被回收. weak reference的语法是: [java] view plain copy WeakReference<Car>weakCar=newWeakReference(Car)(car); 当要获得weak reference引用的object时, 首先需要判断它是否已经被回收: [java] view plain copy weakCar.get(); 如果此方法为空, 那么说明weakCar指向的对象已经被回收了,下面来看一个例子: [java] view plain copy packageweakreference; /** *@authorywchen */ publicclassCar{ privatedoubleprice; privateStringcolour; publicCar(doubleprice,Stringcolour){ this.price=price; this.colour=colour; } publicdoublegetPrice(){ returnprice; } publicvoidsetPrice(doubleprice){ this.price=price; } publicStringgetColour(){ returncolour; } publicvoidsetColour(Stringcolour){ this.colour=colour; } publicStringtoString(){ returncolour+"carcosts$"+price; } } packageweakreference; importjava.lang.ref.WeakReference; /** *@authorywchen */ publicclassTestWeakReference{ publicstaticvoidmain(String[]args){ Carcar=newCar(22000,"silver"); WeakReference<Car>weakCar=newWeakReference<Car>(car); inti=0; while(true){ if(weakCar.get()!=null){ i++; System.out.println("Objectisalivefor"+i+"loops-"+weakCar); }else{ System.out.println("Objecthasbeencollected."); break; } } } } 在上例中, 程序运行一段时间后, 程序打印出"Object has been collected." 说明, weak reference指向的对象的被回收了. ReferenceQueue在weak reference指向的对象被回收后, weak reference本身其实也就没有用了. java提供了一个ReferenceQueue来保存这些所指向的对象已经被回收的reference. 用法是在定义WeakReference的时候将一个ReferenceQueue的对象作为参数传入构造函数. jdk动态代理 面向对象编程(OOP)有一些弊端,为多个不具有继承关系的对象引入同一个公共行为,例如日志、安全监测等,需要在每个对象里引入公共行为,导致程序中产生大量重复代码。不便于维护。所以就有了一个面向对象编程的补充,即面向切面编程(AOP),AOP所关注的是横向,OOP关注的是纵向。AOP的实现,可采用JDK动态代理、CGLIB代理。 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现来完成目标对象的代理。 CBLIB代理:实现原理类似于JDK动态代理,它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层依靠ASM(开源的字节码编辑类库)操作字节码实现,性能比JDK强。 jdk动态代理实现示例 1.新建委托类 [java] view plain copy /** *目标对象实现的接口,用JDK来生成代理对象一定要实现一个接口 *@authoryawenchen *@since2016-11-15 * */ publicinterfaceUserService{ /** *目标方法 */ publicabstractvoidadd(); } [java] view plain copy /** *目标对象 *@authoryawenchen *@since2016-11-15 * */ publicclassUserServiceImplimplementsUserService{ /*(non-Javadoc) *@seedynamic.proxy.UserService#add() */ publicvoidadd(){ System.out.println("--------------------add---------------"); } } UserService 是一个接口,UserServiceImpl 接口的实现类,也称委托类。动态代理要求代理对象必须是接口的实现类。因此UserServiceImpl 实现了UserService 。 2.实现InvocationHandlerj接口 [java] view plain copy importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Method; importjava.lang.reflect.Proxy; /** *实现自己的InvocationHandler *@authorywchen *@since2016-11-15 * */ publicclassMyInvocationHandlerimplementsInvocationHandler{ //目标对象 privateObjecttarget; /** *构造方法 *@paramtarget目标对象 */ publicMyInvocationHandler(Objecttarget){ super(); this.target=target; } /** *执行目标对象的方法 */ publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ //在目标对象的方法执行之前简单的打印一下 System.out.println("------------------before------------------"); //执行目标对象的方法 Objectresult=method.invoke(target,args); //在目标对象的方法执行之后简单的打印一下 System.out.println("-------------------after------------------"); returnresult; } /** *获取目标对象的代理对象 *@return代理对象 */ publicObjectgetProxy(){ returnProxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(),this); } } target属性,表示代理的目标对象。InvocationHandler是负责连接代理对象与目标对象的自定义中间类MyInvocationHandler必须实现的接口,只有一个方法。 public Object invoke(Object proxy, Method method, Object[] args) 参数说明:Proxy表示通过Proxy.newProxyInstance()生成的代理类对象。Method表示目标对象被调用的方法。Args表示目标对象被调用方法的输入参数。 3.通过Proxy类静态函数生成代理对象 [java] view plain copy publicclassProxyTest{ publicstaticvoidmain(String[]args){ //实例化目标对象 UserServiceuserService=newUserSericeImpl(); //实例化InvocationHander MyInvocationHandlerinvocationHandler=newMyInvocationHandler(userService); //根据目标对象生成代理对象 UserServiceproxy=(UserService)invocationHandler.getProxy(); //调用代理对象的方法 proxy.add(); } } 执行结果 ------------------before------------------ --------------------add--------------- -------------------after------------------ 动态代理原理 [java] view plain copy /** *loader:类加载器 *interfaces:目标对象实现的接口 *h:InvocationHandler的实现类 */ publicstaticObjectnewProxyInstance(ClassLoaderloader, Class<?>[]interfaces, InvocationHandlerh) throwsIllegalArgumentException { Objects.requireNonNull(h); finalClass<?>[]intfs=interfaces.clone(); finalSecurityManagersm=System.getSecurityManager(); if(sm!=null){ checkProxyAccess(Reflection.getCallerClass(),loader,intfs); } /* *Lookuporgeneratethedesignatedproxyclass.从缓存中查找或生成目标对象的代理类 */ Class<?>cl=getProxyClass0(loader,intfs); /* *Invokeitsconstructorwiththedesignatedinvocationhandler. */ try{ if(sm!=null){ checkNewProxyPermission(Reflection.getCallerClass(),cl); } //调用代理对象的构造函数(代理对象的构造函数$Proxy0(InvocationHandlerh),通过字节码反编译可以查看生成的代理类) finalConstructor<?>cons=cl.getConstructor(constructorParams); finalInvocationHandlerih=h; if(!Modifier.isPublic(cl.getModifiers())){ AccessController.doPrivileged(newPrivilegedAction<Void>(){ publicVoidrun(){ cons.setAccessible(true); returnnull; } }); } //生成代理类的实例,并把MyInvocationHander的实例作为构造函数参数传入 returncons.newInstance(newObject[]{h}); }catch(IllegalAccessException|InstantiationExceptione){ thrownewInternalError(e.toString(),e); }catch(InvocationTargetExceptione){ Throwablet=e.getCause(); if(tinstanceofRuntimeException){ throw(RuntimeException)t; }else{ thrownewInternalError(t.toString(),t); } }catch(NoSuchMethodExceptione){ thrownewInternalError(e.toString(),e); } } 进到getProxyClass0方法 [java] view plain copy privatestaticClass<?>getProxyClass0(ClassLoaderloader, Class<?>...interfaces){ if(interfaces.length>65535){ thrownewIllegalArgumentException("interfacelimitexceeded"); } //Iftheproxyclassdefinedbythegivenloaderimplementing //thegiveninterfacesexists,thiswillsimplyreturnthecachedcopy; //otherwise,itwillcreatetheproxyclassviatheProxyClassFactory returnproxyClassCache.get(loader,interfaces); } proxyClassCache为WeakCache的实例化对象,在Proxy类中定义,表示代理类的缓存。定义如下: [java] view plain copy privatestaticfinalWeakCache<ClassLoader,Class<?>[],Class<?>>proxyClassCache=newWeakCache<>(newKeyFactory(),newProxyClassFactory()); KeyFactory、ProxyClassFactory是WeakCache的内部静态类。实现了BiFunction接口。WeakCache实例化时作为构造函数参数传入,继承关系如下: 主要的代码如下: [java] view plain copy publicinterfaceBiFunction<T,U,R>{ Rapply(Tt,Uu); } [java] view plain copy privatestaticfinalclassProxyClassFactory implementsBiFunction<ClassLoader,Class<?>[],Class<?>> { //prefixforallproxyclassnames代理类的前缀 privatestaticfinalStringproxyClassNamePrefix="$Proxy"; //nextnumbertouseforgenerationofuniqueproxyclassnames //生成唯一的代理类名称 privatestaticfinalAtomicLongnextUniqueNumber=newAtomicLong(); @Override publicClass<?>apply(ClassLoaderloader,Class<?>[]interfaces){ Map<Class<?>,Boolean>interfaceSet=newIdentityHashMap<>(interfaces.length); for(Class<?>intf:interfaces){ /* *Verifythattheclassloaderresolvesthenameofthis *interfacetothesameClassobject. */ //确保接口的类对象与类加载器加载的类对象相同,且由同一个加载器加载。《深入理解java虚拟机》提到,类加载器虽然只用于实现类的加载动作,但在java程序起的作用远不止于类的加载。对于任何一个类,都需要由加载它的的类加载器和这个类本身一同确立其在java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间,通俗点,比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。interfaceClass=Class.forName(intf.getName(),false,loader);验证类是否相等,实现原理如上所述。 Class<?>interfaceClass=null; try{ interfaceClass=Class.forName(intf.getName(),false,loader); }catch(ClassNotFoundExceptione){ } if(interfaceClass!=intf){ thrownewIllegalArgumentException( intf+"isnotvisiblefromclassloader"); } /* *VerifythattheClassobjectactuallyrepresentsan *interface.验证类对象表示的是接口 */ if(!interfaceClass.isInterface()){ thrownewIllegalArgumentException( interfaceClass.getName()+"isnotaninterface"); } /* *Verifythatthisinterfaceisnotaduplicate.验证接口未重复 */ if(interfaceSet.put(interfaceClass,Boolean.TRUE)!=null){ thrownewIllegalArgumentException( "repeatedinterface:"+interfaceClass.getName()); } } StringproxyPkg=null;//packagetodefineproxyclassin定义待生成的代理类所在包名 intaccessFlags=Modifier.PUBLIC|Modifier.FINAL; /* *Recordthepackageofanon-publicproxyinterfacesothatthe *proxyclasswillbedefinedinthesamepackage.Verifythat *allnon-publicproxyinterfacesareinthesamepackage.非public修饰的代理接口,需要定义在相同的包中,如果非public修饰的接口不在相同包,会因访问权限的限制而无法访问。intf.getModifiers()返回的是一个整数,用不同的位开关表示接口中public/final修饰符的使用情况。 */ for(Class<?>intf:interfaces){ intflags=intf.getModifiers(); if(!Modifier.isPublic(flags)){ accessFlags=Modifier.FINAL; Stringname=intf.getName(); intn=name.lastIndexOf('.'); Stringpkg=((n==-1)?"":name.substring(0,n+1)); if(proxyPkg==null){ proxyPkg=pkg;//代理对象的包名,如com.aop }elseif(!pkg.equals(proxyPkg)){ thrownewIllegalArgumentException( "non-publicinterfacesfromdifferentpackages"); } } } if(proxyPkg==null){ //ifnonon-publicproxyinterfaces,usecom.sun.proxypackage proxyPkg=ReflectUtil.PROXY_PACKAGE+"."; } /* *Chooseanamefortheproxyclasstogenerate. */ longnum=nextUniqueNumber.getAndIncrement(); StringproxyName=proxyPkg+proxyClassNamePrefix+num; /* *Generatethespecifiedproxyclass. *生成目标对象的代理类的字节码,并保存到硬盘中。 */ byte[]proxyClassFile=ProxyGenerator.generateProxyClass( proxyName,interfaces,accessFlags); try{ //返回代理类对象,将字节码加载到内存中 returndefineClass0(loader,proxyName, proxyClassFile,0,proxyClassFile.length); }catch(ClassFormatErrore){ /* *AClassFormatErrorheremeansthat(barringbugsinthe *proxyclassgenerationcode)therewassomeother *invalidaspectoftheargumentssuppliedtotheproxy *classcreation(suchasvirtualmachinelimitations *exceeded). */ thrownewIllegalArgumentException(e.toString()); } } } [java] view plain copy /** *映射接口数组到最后键的函数 *接口数组映射到最优键对象上(如实例化Key1时,接口作为Key1的构造函数参数,保存到Key1中),同时,Key1/Key2/KeyX继承了WeakReference弱引用类类,因此接口所在的类对象被弱引用 */ privatestaticfinalclassKeyFactory implementsBiFunction<ClassLoader,Class<?>[],Object> { @Override publicObjectapply(ClassLoaderclassLoader,Class<?>[]interfaces){ switch(interfaces.length){ case1:returnnewKey1(interfaces[0]);//themostfrequent case2:returnnewKey2(interfaces[0],interfaces[1]); case0:returnkey0; default:returnnewKeyX(interfaces); } } } WeakCache类中定义的map变量如下: [java] view plain copy privatefinalConcurrentMap<Object,ConcurrentMap<Object,Supplier<V>>>map=newConcurrentHashMap<>(); 双层map映射,第一层key为ClassLoader,第二层key为接口的弱引用对象,value为代理类的Class对象。怎么看出是弱引用的呢,value中存放的值是一个类,该类继承了弱引用类WeakReference,我们的代理类在对象实例化时,通过构造函数传入。为对象添加引用,可看WeakReference用法。第一层是类加载器,第二层才是类对象,为什么不用一层,代理类对象作为键呢,这里就涉及到类加载器的使用。记住一点,类的唯一性是由类加载器和类本身共同决定的。 对Supplier接口,Factory类进行说明,接下来的代码中会用到。 调用proxyClassCache.get(loader, interfaces),进入WeakCache的get方法。代码如下: [java] view plain copy publicVget(Kkey,Pparameter){ Objects.requireNonNull(parameter); expungeStaleEntries(); //refQueue的类型为ReferenceQueue,存放对象的弱引用,CacheKey继承了WeakReference,因此key(ClassLoader)所在对象被弱引用,对象的应用存放在队列refQueue中。 ObjectcacheKey=CacheKey.valueOf(key,refQueue); //lazilyinstallthe2ndlevelvaluesMapfortheparticularcacheKey //生成第一层key,从缓存中获取valuesMap,如果为空,则新建ConcurrentHashMap实例,把当前加载器和ConcurrentHashMap实例放到缓存中。 ConcurrentMap<Object,Supplier<V>>valuesMap=map.get(cacheKey); if(valuesMap==null){ ConcurrentMap<Object,Supplier<V>>oldValuesMap =map.putIfAbsent(cacheKey, valuesMap=newConcurrentHashMap<>()); if(oldValuesMap!=null){ valuesMap=oldValuesMap; } } //createsubKeyandretrievethepossibleSupplier<V>storedbythat //subKeyfromvaluesMap //subKeyFactory是Proxy类的内部静态类KeyFactory的实例对象 //valueFactory是Proxy类的内容静态类ProxyClassFactory的实例对象 //subKeyFactory.apply(key,parameter)返回接口的弱引用对象。subKey,即接口的弱引用对象作为第二层映射的键 ObjectsubKey=Objects.requireNonNull(subKeyFactory.apply(key,parameter)); Supplier<V>supplier=valuesMap.get(subKey); Factoryfactory=null; while(true){ if(supplier!=null){ //suppliermightbeaFactoryoraCacheValue<V>instance,supplier不为空,缓存中存在代理类 Vvalue=supplier.get(); if(value!=null){//value不为空,即代理类存在,将代理类返回。 returnvalue; } } //elsenosupplierincache //orasupplierthatreturnednull(couldbeaclearedCacheValue //oraFactorythatwasn'tsuccessfulininstallingtheCacheValue) //lazilyconstructaFactory if(factory==null){ factory=newFactory(key,parameter,subKey,valuesMap); } if(supplier==null){ supplier=valuesMap.putIfAbsent(subKey,factory); if(supplier==null){ //successfullyinstalledFactory supplier=factory; } //elseretrywithwinningsupplier }else{ if(valuesMap.replace(subKey,supplier,factory)){ //successfullyreplaced //clearedCacheEntry/unsuccessfulFactory //withourFactory supplier=factory; }else{ //retrywithcurrentsupplier supplier=valuesMap.get(subKey); } } } } 上面执行流程中,主要的两个步骤为: Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); subKey为接口对象的弱引用。 进入Proxy类的内部静态类KeyFactory,查看apply方法(本文前面提到的KeyFactory类)。 V value = supplier.get(); value为缓存中的代理类对象,Supplier是个接口,实现代码是在接口的实现类Factory中, 进入WeakCache类的内部类Factory,查看get方法。如下: Supplier是接口 [java] view plain copy publicinterfaceSupplier<T>{ /** *Getsaresult. * *@returnaresult */ Tget(); } } Factory是WeakCache的内部类, Factory实现了接口Supplier [java] view plain copy privatefinalclassFactoryimplementsSupplier<V>{ privatefinalKkey; privatefinalPparameter; privatefinalObjectsubKey; privatefinalConcurrentMap<Object,Supplier<V>>valuesMap; Factory(Kkey,Pparameter,ObjectsubKey, ConcurrentMap<Object,Supplier<V>>valuesMap){ this.key=key; this.parameter=parameter; this.subKey=subKey; this.valuesMap=valuesMap; } @Override publicsynchronizedVget(){//serializeaccess //re-check Supplier<V>supplier=valuesMap.get(subKey); if(supplier!=this){ //somethingchangedwhilewewerewaiting: //mightbethatwewerereplacedbyaCacheValue //orwereremovedbecauseoffailure-> //returnnulltosignalWeakCache.get()toretry //theloop returnnull; } //elsestillus(supplier==this) //createnewvalue Vvalue=null; try{ //valueFactory.apply(key,parameter)返回代理类对象,即Class对象。 //如果value不为空,说明缓存中已经存在代理类,可以直接返回。 //通过前面的判断,已经能确定缓存中存在代理类,否则,程序是走不到这里来的。 value=Objects.requireNonNull(valueFactory.apply(key,parameter)); }finally{ if(value==null){//removeusonfailure valuesMap.remove(subKey,this); } } //theonlypathtoreachhereiswithnon-nullvalue assertvalue!=null; //wrapvaluewithCacheValue(WeakReference) CacheValue<V>cacheValue=newCacheValue<>(value); //tryreplacinguswithCacheValue(thisshouldalwayssucceed) if(valuesMap.replace(subKey,this,cacheValue)){ //putalsoinreverseMap reverseMap.put(cacheValue,Boolean.TRUE); }else{ thrownewAssertionError("Shouldnotreachhere"); } //successfullyreplaceduswithnewCacheValue->returnthevalue //wrappedbyit returnvalue; } } 在Facotry类的get方法中,value是由valueFactory.apply(key, parameter)生成,返回代理类Class对象。具体的实现可在本文前面提到的ValueFactory中查看。 JDK动态代理实现原理 Java WeakReference的理解与使用