栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

一个简单JDK版动态代理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一个简单JDK版动态代理

本文实例为大家分享了手动实现的一个简单JDK版动态代理,供大家参考,具体内容如下

一.实现步骤

1.根据目标类的接口类型生成代理类的java文件。
2.编译代理类java文件为.class字节码文件。
3.将编译好的字节码文件加载到jvm中。
4.生成代理类对象并返回。

二.代码实现

1.Proxy类

public class CLProxy  {
  private static final String ENTER= "rn";
  private static final String PAKAGE=CLProxy.class.getPackage().toString()+";";
  private static final String CLASS_NAME="$Proxy";
  private static final AtomicInteger NUMBER= new AtomicInteger(0);
  public static Object newProxyInstance(CLClassLoader classLoader, Class[] interfaces,CLInvocationHandler h) throws Exception{
    String className =CLASS_NAME+NUMBER.getAndIncrement();
    //遍历所有的接口生成java 文件
    String javaString = createJavaString(interfaces, className);
    String parentPath = CLProxy.class.getResource("").getPath();
    File file =new File(parentPath,className+".java" );
    FileWriter writer  = new FileWriter(file);
    writer.write(javaString);
    writer.flush();
    writer.close();
    //System.out.println(file);
    //编译
    JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager standardFileManager = systemJavaCompiler.getStandardFileManager(null, null, null);
    Iterable javaFileObjects = standardFileManager.getJavaFileObjects(file);
    JavaCompiler.CompilationTask task = systemJavaCompiler.getTask(null, standardFileManager, null, null, null, javaFileObjects);
    task.call();
    standardFileManager.close();
    //创建实例
    Class aClass = classLoader.findClass(className);
    Constructor constructor = aClass.getConstructor(CLInvocationHandler.class);
    Object instance = constructor.newInstance(h);
    //file.delete();
    return instance;
  }
 
  
  private static String createJavaString(Class[] interfaces , String className ){
 
    StringBuffer buffer  = new StringBuffer();
    buffer.append(PAKAGE+ENTER);
    buffer.append("import java.lang.reflect.Method;"+ ENTER);
 
    StringBuffer interfaceString= new StringBuffer();
    int length= interfaces.length;
    for (int i = 0; i clazz= interfaces[i];
      Method[] methods = clazz.getMethods();
      for (Method method : methods){
 String returnTypeString = method.getReturnType().getName();
 
 Class[] parameterTypes = method.getParameterTypes();
 StringBuffer paramTypeString = new StringBuffer();
 StringBuffer methodParamString = new StringBuffer();
 StringBuffer invokeParamString = new StringBuffer();
 
 paramTypeString.append("new Class[]{");
 int paramLength= parameterTypes.length;
 for (int j =0 ; j paramClazz= parameterTypes[j];
   paramTypeString.append(paramClazz.getName()+".class");
   String paramFieldName = "var"+j;
   methodParamString.append(paramClazz.getName() +" "+paramFieldName);
   invokeParamString.append(paramFieldName);
   if (j!= paramLength-1){
     paramTypeString.append(",");
     methodParamString.append(",");
     invokeParamString.append(",");
   }
 }
 paramTypeString.append("}");
 int modifiers = method.getModifiers();
 if (Modifier.isPublic(modifiers)){
   buffer.append("public");
 }else if (Modifier.isPrivate(modifiers)){
   buffer.append("private");
 }else if (Modifier.isProtected(modifiers)){
   buffer.append("protected");
 }
 buffer.append(" final "+returnTypeString+" "+ method.getName()+"("+methodParamString+"){"+ ENTER);
   buffer.append("try{"+ENTER);
 
 buffer.append("Method method = "+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 = new StringBuffer("new Object[]{"+invokeParamString.toString()+"}");
   }
   buffer.append("this.handler.invoke(this,method,"+invokeParamString+");"+ENTER);
   buffer.append("}catch(Throwable e){"+ENTER);
   buffer.append("e.printStackTrace();"+ENTER);
   buffer.append("}"+ENTER);
   if (!"void".equals(returnTypeString)){
     buffer.append("return null;"+ENTER);
   }
 buffer.append("}"+ENTER);
      }
    }
 
    buffer.append("}");
    return buffer.toString();
  }
 
  public static void main(String[] args) throws Exception {
    Person person = (Person)CLProxy.newProxyInstance(new CLClassLoader(), XiaoMing.class.getInterfaces(), new CLInvocationHandler() {
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 System.out.println("before");
 
 Object result= method.invoke(new XiaoMing(), args);
 System.out.println("after");
 return result;
      }
    });
    String laoxu = person.call("laoxu");
    System.out.println(laoxu);
    
    Person person2= (Person)CLProxy.newProxyInstance(new CLClassLoader(), XiaoMing.class.getInterfaces(), new CLInvocationHandler() {
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 System.out.println("before");
 
 Object result= method.invoke(new XiaoMing(), args);
 System.out.println("after");
 return result;
      }
    });
 
    System.out.println(person2.getClass());
 
  }
}

2.InvocationHandler接口

public interface CLInvocationHandler {
 
  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable;
 
}

3.ClassLoader类加载器

public class CLClassLoader extends ClassLoader {
 
  private File classPathFile;
 
  public CLClassLoader(){
 
    String classPath = CLClassLoader.class.getResource("").getPath();
 
    this.classPathFile= new File(classPath);
  }
 
 
  @Override
  protected Class findClass(String name) throws ClassNotFoundException {
 
 
    String className = CLClassLoader.class.getPackage().getName()+"."+name;
 
 
 
    if (classPathFile!= null ){
 
 
      File classFile = new File(classPathFile, name.replace("\.", "/") + ".class");
 
 
      if (classFile.exists()){
 
 
 FileInputStream inputStream =null;
 
 ByteArrayOutputStream outputStream = null;
 try{
   inputStream=new FileInputStream(classFile);
 
   outputStream= new ByteArrayOutputStream();
 
   byte[] bytes = new byte[1024];
   int len;
   while ((len=inputStream.read(bytes))!=-1){
     outputStream.write(bytes,0,len);
   }
   return defineClass(className,outputStream.toByteArray(),0,outputStream.size());
 }catch (Exception e){
   e.printStackTrace();
 }finally {
   if (inputStream!= null){
     try {
inputStream.close();
     } catch (IOException e) {
e.printStackTrace();
     }
   }
   if (outputStream!=null){
     try {
outputStream.close();
     } catch (IOException e) {
e.printStackTrace();
     }
   }
 }
 
 
 
      }
 
 
 
 
    }
    return super.findClass(name);
  }
}

4.测试使用的接口与目标类

//测试使用的接口
public interface Person {
 
  void eat();
 
  String call(String name);
}
 
 
//测试使用目标类
public class XiaoMing implements Person {
  @Override
  public void eat() {
    System.out.println("吃东西");
  }
 
  //@Override
  public String call(String name) {
    return name;
  }
}

注意测试方法在CLProxy 的main 方法中。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/136951.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号