一个简单JDK版动态代理
本文实例为大家分享了手动实现的一个简单JDK版动态代理,供大家参考,具体内容如下
一.实现步骤
1.根据目标类的接口类型生成代理类的java文件。
2.编译代理类java文件为.class字节码文件。
3.将编译好的字节码文件加载到jvm中。
4.生成代理类对象并返回。
二.代码实现
1.Proxy类
publicclassCLProxy{ privatestaticfinalStringENTER="\r\n"; privatestaticfinalStringPAKAGE=CLProxy.class.getPackage().toString()+";"; privatestaticfinalStringCLASS_NAME="$Proxy"; privatestaticfinalAtomicIntegerNUMBER=newAtomicInteger(0); publicstaticObjectnewProxyInstance(CLClassLoaderclassLoader,Class>[]interfaces,CLInvocationHandlerh)throwsException{ StringclassName=CLASS_NAME+NUMBER.getAndIncrement(); //遍历所有的接口生成java文件 StringjavaString=createJavaString(interfaces,className); StringparentPath=CLProxy.class.getResource("").getPath(); Filefile=newFile(parentPath,className+".java"); FileWriterwriter=newFileWriter(file); writer.write(javaString); writer.flush(); writer.close(); //System.out.println(file); //编译 JavaCompilersystemJavaCompiler=ToolProvider.getSystemJavaCompiler(); StandardJavaFileManagerstandardFileManager=systemJavaCompiler.getStandardFileManager(null,null,null); IterablejavaFileObjects=standardFileManager.getJavaFileObjects(file); JavaCompiler.CompilationTasktask=systemJavaCompiler.getTask(null,standardFileManager,null,null,null,javaFileObjects); task.call(); standardFileManager.close(); //创建实例 Class>aClass=classLoader.findClass(className); Constructor>constructor=aClass.getConstructor(CLInvocationHandler.class); Objectinstance=constructor.newInstance(h); //file.delete(); returninstance; } /** *生成java文件 *@paraminterfaces *@return */ privatestaticStringcreateJavaString(Class>[]interfaces,StringclassName){ StringBufferbuffer=newStringBuffer(); buffer.append(PAKAGE+ENTER); buffer.append("importjava.lang.reflect.Method;"+ENTER); StringBufferinterfaceString=newStringBuffer(); intlength=interfaces.length; for(inti=0;iclazz=interfaces[i]; Method[]methods=clazz.getMethods(); for(Methodmethod:methods){ StringreturnTypeString=method.getReturnType().getName(); Class>[]parameterTypes=method.getParameterTypes(); StringBufferparamTypeString=newStringBuffer(); StringBuffermethodParamString=newStringBuffer(); StringBufferinvokeParamString=newStringBuffer(); paramTypeString.append("newClass[]{"); intparamLength=parameterTypes.length; for(intj=0;j paramClazz=parameterTypes[j]; paramTypeString.append(paramClazz.getName()+".class"); StringparamFieldName="var"+j; methodParamString.append(paramClazz.getName()+""+paramFieldName); invokeParamString.append(paramFieldName); if(j!=paramLength-1){ paramTypeString.append(","); methodParamString.append(","); invokeParamString.append(","); } } paramTypeString.append("}"); intmodifiers=method.getModifiers(); if(Modifier.isPublic(modifiers)){ buffer.append("public"); }elseif(Modifier.isPrivate(modifiers)){ buffer.append("private"); }elseif(Modifier.isProtected(modifiers)){ buffer.append("protected"); } buffer.append("final"+returnTypeString+""+method.getName()+"("+methodParamString+"){"+ENTER); buffer.append("try{"+ENTER); buffer.append("Methodmethod="+clazz.getName()+".class.getMethod(\""+method.getName()+"\","+paramTypeString+");"+ENTER); if(!"void".equals(returnTypeString)){ buffer.append("return("+returnTypeString+")"); } if(invokeParamString.toString().length()==0){ invokeParamString.append("null"); }else{ invokeParamString=newStringBuffer("newObject[]{"+invokeParamString.toString()+"}"); } buffer.append("this.handler.invoke(this,method,"+invokeParamString+");"+ENTER); buffer.append("}catch(Throwablee){"+ENTER); buffer.append("e.printStackTrace();"+ENTER); buffer.append("}"+ENTER); if(!"void".equals(returnTypeString)){ buffer.append("returnnull;"+ENTER); } buffer.append("}"+ENTER); } } buffer.append("}"); returnbuffer.toString(); } publicstaticvoidmain(String[]args)throwsException{ Personperson=(Person)CLProxy.newProxyInstance(newCLClassLoader(),XiaoMing.class.getInterfaces(),newCLInvocationHandler(){ @Override publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ System.out.println("before"); Objectresult=method.invoke(newXiaoMing(),args); System.out.println("after"); returnresult; } }); Stringlaoxu=person.call("laoxu"); System.out.println(laoxu); /*person.eat(); Class>[]interfaces=person.getClass().getInterfaces(); for(Class>in:interfaces){ System.out.println(in.getName()); } */ Personperson2=(Person)CLProxy.newProxyInstance(newCLClassLoader(),XiaoMing.class.getInterfaces(),newCLInvocationHandler(){ @Override publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ System.out.println("before"); Objectresult=method.invoke(newXiaoMing(),args); System.out.println("after"); returnresult; } }); System.out.println(person2.getClass()); } }
2.InvocationHandler接口
publicinterfaceCLInvocationHandler{ publicObjectinvoke(Objectproxy,Methodmethod,Object[]args) throwsThrowable; }
3.ClassLoader类加载器
publicclassCLClassLoaderextendsClassLoader{ privateFileclassPathFile; publicCLClassLoader(){ StringclassPath=CLClassLoader.class.getResource("").getPath(); this.classPathFile=newFile(classPath); } @Override protectedClass>findClass(Stringname)throwsClassNotFoundException{ StringclassName=CLClassLoader.class.getPackage().getName()+"."+name; if(classPathFile!=null){ FileclassFile=newFile(classPathFile,name.replace("\\.","/")+".class"); if(classFile.exists()){ FileInputStreaminputStream=null; ByteArrayOutputStreamoutputStream=null; try{ inputStream=newFileInputStream(classFile); outputStream=newByteArrayOutputStream(); byte[]bytes=newbyte[1024]; intlen; while((len=inputStream.read(bytes))!=-1){ outputStream.write(bytes,0,len); } returndefineClass(className,outputStream.toByteArray(),0,outputStream.size()); }catch(Exceptione){ e.printStackTrace(); }finally{ if(inputStream!=null){ try{ inputStream.close(); }catch(IOExceptione){ e.printStackTrace(); } } if(outputStream!=null){ try{ outputStream.close(); }catch(IOExceptione){ e.printStackTrace(); } } } } } returnsuper.findClass(name); } }
4.测试使用的接口与目标类
//测试使用的接口 publicinterfacePerson{ voideat(); Stringcall(Stringname); } //测试使用目标类 publicclassXiaoMingimplementsPerson{ @Override publicvoideat(){ System.out.println("吃东西"); } //@Override publicStringcall(Stringname){ returnname; } }
注意测试方法在CLProxy的main方法中。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。