java 1.8 动态代理源码深度分析
JDK8动态代理源码分析
动态代理的基本使用就不详细介绍了:
例子:
classproxyedimplementspro{ @Override publicvoidtext(){ System.err.println("本方法"); } } interfacepro{ voidtext(); } publicclassJavaProxyimplementsInvocationHandler{ privateObjectsource; publicJavaProxy(Objectsource){ super(); this.source=source; } publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ System.out.println("before"); Objectinvoke=method.invoke(source,args); System.out.println("after"); returninvoke; } publicObjectgetProxy(){ returnProxy.newProxyInstance(getClass().getClassLoader(),source.getClass().getInterfaces(),this); } publicstaticvoidmain(String[]args)throwsIllegalAccessException,InvocationTargetException,InstantiationException,NoSuchMethodException{ //第一种,自己写 //1.设置saveGeneratedFiles值为true则生成class字节码文件方便分析 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); //2.获取动态代理类 ClassproxyClazz=Proxy.getProxyClass(pro.class.getClassLoader(),pro.class); //3.获得代理类的构造函数,并传入参数类型InvocationHandler.class Constructorconstructor=proxyClazz.getConstructor(InvocationHandler.class); //4.通过构造函数来创建动态代理对象,将自定义的InvocationHandler实例传入 proiHello=(pro)constructor.newInstance(newJavaProxy(newproxyed())); //5.通过代理对象调用目标方法 iHello.text(); //第二种,调用JDK提供的方法,实现了2~4步 Proxy.newProxyInstance(JavaProxy.class.getClassLoader(),proxyed.class.getInterfaces(),newJavaProxy(newproxyed())); } }
入口:newProxyInstance
publicstaticObjectnewProxyInstance(ClassLoaderloader,Class>[]interfaces,InvocationHandlerh)throwsIllegalArgumentException{ //Objects.requireNonNull判空方法,之后所有的单纯的判断null并抛异常,都是此方法 Objects.requireNonNull(h); //clone类实现的所有接口 finalClass>[]intfs=interfaces.clone(); //获取当前系统安全接口 finalSecurityManagersm=System.getSecurityManager(); if(sm!=null){ //Reflection.getCallerClass返回调用该方法的方法的调用类;loader:接口的类加载器 //进行包访问权限、类加载器权限等检查 checkProxyAccess(Reflection.getCallerClass(),loader,intfs); } /* *Lookuporgeneratethedesignatedproxyclass. *查找或生成代理类 */ Class>cl=getProxyClass0(loader,intfs); /* *Invokeitsconstructorwiththedesignatedinvocationhandler. *使用指定的调用处理程序调用它的构造函数 */ try{ if(sm!=null){ checkNewProxyPermission(Reflection.getCallerClass(),cl); } //获取构造 finalConstructor>cons=cl.getConstructor(constructorParams); finalInvocationHandlerih=h; if(!Modifier.isPublic(cl.getModifiers())){ AccessController.doPrivileged(newPrivilegedAction(){ publicVoidrun(){ cons.setAccessible(true); returnnull; } }); } //返回代理对象 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); } }
从上面的分析中可以看出,newProxyInstance帮我们执行了生成代理类----获取构造器----生成代理对象这三步;
我们重点分析生成代理类
getProxyClass0
/** *acacheofproxyclasses:动态代理类的弱缓存容器 *KeyFactory:根据接口的数量,映射一个最佳的key生成函数,其中表示接口的类对象被弱引用;也就是key对象被弱引用继承自WeakReference(key0、key1、key2、keyX),保存接口密钥(hash值) *ProxyClassFactory:生成动态类的工厂 *注意,两个都实现了BiFunction[],Object>接口 */ privatestaticfinalWeakCache [],Class>>proxyClassCache=newWeakCache<>(newKeyFactory(),newProxyClassFactory()); /** *Generateaproxyclass.MustcallthecheckProxyAccessmethod *toperformpermissionchecksbeforecallingthis. *生成代理类,调用前必须进行checkProxyAccess权限检查,所以newProxyInstance进行了权限检查 */ privatestaticClass>getProxyClass0(ClassLoaderloader,Class>...interfaces){ //实现接口的最大数量<65535;谁写的类能实现这么多接口 if(interfaces.length>65535){ thrownewIllegalArgumentException("interfacelimitexceeded"); } //Iftheproxyclassdefinedbythegivenloaderimplementing //thegiveninterfacesexists,thiswillsimplyreturnthecachedcopy; //otherwise,itwillcreatetheproxyclassviatheProxyClassFactory //如果缓存中有,就直接返回,否则会生成 returnproxyClassCache.get(loader,interfaces); }
proxyClassCache.get
publicVget(Kkey,Pparameter){ //key:类加载器;parameter:接口数组 Objects.requireNonNull(parameter); //清除已经被GC回收的弱引用 expungeStaleEntries(); //CacheKey弱引用类,refQueue已经被回收的弱引用队列;构建一个CacheKey ObjectcacheKey=CacheKey.valueOf(key,refQueue); //map一级缓存,获取valuesMap二级缓存 ConcurrentMap
supplier.get
这个方法中会调用ProxyClassFactory的apply方法,就不过多介绍
ProxyClassFactory.apply
publicClass>apply(ClassLoaderloader,Class>[]interfaces){ Map,Boolean>interfaceSet=newIdentityHashMap<>(interfaces.length); for(Class>intf:interfaces){ /* *VerifythattheclassloaderresolvesthenameofthisinterfacetothesameClassobject. *类加载器和接口名解析出的是同一个 */ Class>interfaceClass=null; try{ interfaceClass=Class.forName(intf.getName(),false,loader); }catch(ClassNotFoundExceptione){ } if(interfaceClass!=intf){ thrownewIllegalArgumentException(intf+"isnotvisiblefromclassloader"); } /* *VerifythattheClassobjectactuallyrepresentsaninterface. *确保是一个接口 */ 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-publicproxyinterfacesothattheproxyclasswillbedefinedinthesamepackage. *Verifythatallnon-publicproxyinterfacesareinthesamepackage. *验证所有非公共的接口在同一个包内;公共的就无需处理 */ 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; }elseif(!pkg.equals(proxyPkg)){ thrownewIllegalArgumentException("non-publicinterfacesfromdifferentpackages"); } } } if(proxyPkg==null){ //ifnonon-publicproxyinterfaces,usecom.sun.proxypackage proxyPkg=ReflectUtil.PROXY_PACKAGE+"."; } /* *Chooseanamefortheproxyclasstogenerate. *proxyClassNamePrefix=$Proxy *nextUniqueNumber是一个原子类,确保多线程安全,防止类名重复,类似于:$Proxy0,$Proxy1...... */ 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()); } }
ProxyGenerator.generateProxyClass
publicstaticbyte[]generateProxyClass(finalStringname,Class>[]interfaces,intaccessFlags){ ProxyGeneratorgen=newProxyGenerator(name,interfaces,accessFlags); //真正生成字节码的方法 finalbyte[]classFile=gen.generateClassFile(); //如果saveGeneratedFiles为true则生成字节码文件,所以在开始我们要设置这个参数 //当然,也可以通过返回的bytes自己输出 if(saveGeneratedFiles){ java.security.AccessController.doPrivileged(newjava.security.PrivilegedAction(){ publicVoidrun(){ try{ inti=name.lastIndexOf('.'); Pathpath; if(i>0){ Pathdir=Paths.get(name.substring(0,i).replace('.',File.separatorChar)); Files.createDirectories(dir); path=dir.resolve(name.substring(i+1,name.length())+".class"); }else{ path=Paths.get(name+".class"); } Files.write(path,classFile); returnnull; }catch(IOExceptione){ thrownewInternalError("I/Oexceptionsavinggeneratedfile:"+e); } } }); } returnclassFile; }
最终方法
privatebyte[]generateClassFile(){ /*============================================================ *Step1:AssembleProxyMethodobjectsforallmethodstogenerateproxydispatchingcodefor. *步骤1:为所有方法生成代理调度代码,将代理方法对象集合起来。 */ //增加hashcode、equals、toString方法 addProxyMethod(hashCodeMethod,Object.class); addProxyMethod(equalsMethod,Object.class); addProxyMethod(toStringMethod,Object.class); //增加接口方法 for(Class>intf:interfaces){ for(Methodm:intf.getMethods()){ addProxyMethod(m,intf); } } /* *验证方法签名相同的一组方法,返回值类型是否相同;意思就是重写方法要方法签名和返回值一样 */ for(Listsigmethods:proxyMethods.values()){ checkReturnTypes(sigmethods); } /*============================================================ *Step2:AssembleFieldInfoandMethodInfostructsforalloffieldsandmethodsintheclasswearegenerating. *为类中的方法生成字段信息和方法信息 */ try{ //增加构造方法 methods.add(generateConstructor()); for(List sigmethods:proxyMethods.values()){ for(ProxyMethodpm:sigmethods){ //addstaticfieldformethod'sMethodobject fields.add(newFieldInfo(pm.methodFieldName, "Ljava/lang/reflect/Method;", ACC_PRIVATE|ACC_STATIC)); //generatecodeforproxymethodandaddit methods.add(pm.generateMethod()); } } //增加静态初始化信息 methods.add(generateStaticInitializer()); }catch(IOExceptione){ thrownewInternalError("unexpectedI/OException",e); } if(methods.size()>65535){ thrownewIllegalArgumentException("methodlimitexceeded"); } if(fields.size()>65535){ thrownewIllegalArgumentException("fieldlimitexceeded"); } /*============================================================ *Step3:Writethefinalclassfile. *步骤3:编写最终类文件 */ /* *Makesurethatconstantpoolindexesarereservedforthefollowingitemsbeforestartingtowritethefinalclassfile. *在开始编写最终类文件之前,确保为下面的项目保留常量池索引。 */ cp.getClass(dotToSlash(className)); cp.getClass(superclassName); for(Class>intf:interfaces){ cp.getClass(dotToSlash(intf.getName())); } /* *Disallownewconstantpooladditionsbeyondthispoint,sinceweareabouttowritethefinalconstantpooltable. *设置只读,在这之前不允许在常量池中增加信息,因为要写常量池表 */ cp.setReadOnly(); ByteArrayOutputStreambout=newByteArrayOutputStream(); DataOutputStreamdout=newDataOutputStream(bout); try{ //u4magic; dout.writeInt(0xCAFEBABE); //u2次要版本; dout.writeShort(CLASSFILE_MINOR_VERSION); //u2主版本 dout.writeShort(CLASSFILE_MAJOR_VERSION); cp.write(dout);//(writeconstantpool) //u2访问标识; dout.writeShort(accessFlags); //u2本类名; dout.writeShort(cp.getClass(dotToSlash(className))); //u2父类名; dout.writeShort(cp.getClass(superclassName)); //u2接口; dout.writeShort(interfaces.length); //u2interfaces[interfaces_count]; for(Class>intf:interfaces){ dout.writeShort(cp.getClass( dotToSlash(intf.getName()))); } //u2字段; dout.writeShort(fields.size()); //field_infofields[fields_count]; for(FieldInfof:fields){ f.write(dout); } //u2方法; dout.writeShort(methods.size()); //method_infomethods[methods_count]; for(MethodInfom:methods){ m.write(dout); } //u2类文件属性:对于代理类来说没有类文件属性; dout.writeShort(0);//(noClassFileattributesforproxyclasses) }catch(IOExceptione){ thrownewInternalError("unexpectedI/OException",e); } returnbout.toByteArray(); }
生成的字节码反编译
finalclass$Proxy0extendsProxyimplementspro{ //fields privatestaticMethodm1; privatestaticMethodm2; privatestaticMethodm3; privatestaticMethodm0; public$Proxy0(InvocationHandlervar1)throws{ super(var1); } publicfinalbooleanequals(Objectvar1)throws{ try{ return((Boolean)super.h.invoke(this,m1,newObject[]{var1})).booleanValue(); }catch(RuntimeException|Errorvar3){ throwvar3; }catch(Throwablevar4){ thrownewUndeclaredThrowableException(var4); } } publicfinalStringtoString()throws{ try{ return(String)super.h.invoke(this,m2,(Object[])null); }catch(RuntimeException|Errorvar2){ throwvar2; }catch(Throwablevar3){ thrownewUndeclaredThrowableException(var3); } } publicfinalvoidtext()throws{ try{ //实际就是调用代理类的invoke方法 super.h.invoke(this,m3,(Object[])null); }catch(RuntimeException|Errorvar2){ throwvar2; }catch(Throwablevar3){ thrownewUndeclaredThrowableException(var3); } } publicfinalinthashCode()throws{ try{ return((Integer)super.h.invoke(this,m0,(Object[])null)).intValue(); }catch(RuntimeException|Errorvar2){ throwvar2; }catch(Throwablevar3){ thrownewUndeclaredThrowableException(var3); } } static{ try{ //这里每个方法对象和类的实际方法绑定 m1=Class.forName("java.lang.Object").getMethod("equals",newClass[]{Class.forName("java.lang.Object")}); m2=Class.forName("java.lang.Object").getMethod("toString",newClass[0]); m3=Class.forName("spring.commons.api.study.CreateModel.pro").getMethod("text",newClass[0]); m0=Class.forName("java.lang.Object").getMethod("hashCode",newClass[0]); }catch(NoSuchMethodExceptionvar2){ thrownewNoSuchMethodError(var2.getMessage()); }catch(ClassNotFoundExceptionvar3){ thrownewNoClassDefFoundError(var3.getMessage()); } } }
以上这篇java1.8动态代理源码深度分析就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。