一个简单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;jparamClazz=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方法中。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。