zoukankan      html  css  js  c++  java
  • Java-马士兵设计模式学习笔记-代理模式--动态代理 修改成可以代理任意接口

    一、概述

    1.目标:把Proxy修改成可以代理任意接口及其任意方法

    2.思路:

    (1)代理任意接口:把接口类型作为参数传给Proxy的newProxyInstance(Class interfze)

    (2)代理任意方法:用interfze.getMethods()取出所有方法,拼接实现方法的字符串

    二、代码

    1.Movable.java

    2.Tank.java

    3.Proxy.java

    4.Client.java

    1.Movable.java

    1 package proxy;
    2 
    3 public interface Movable {
    4     public void move();
    5     public void stop();
    6 }

    2.Tank.java

     1 package proxy;
     2 
     3 import java.util.Random;
     4 
     5 public class Tank implements Movable {
     6 
     7     @Override
     8     public void move() {
     9         System.out.println("Tank moving.......");
    10         try {
    11             Thread.sleep(new Random().nextInt(2000));
    12         } catch (InterruptedException e) {
    13             e.printStackTrace();
    14         }
    15     }
    16 
    17     @Override
    18     public void stop() {
    19         System.out.println("Tank stopping.......");
    20         
    21     }
    22 
    23 }

    3.Proxy.java

     1 package proxy;
     2 
     3 import java.io.File;
     4 import java.io.FileWriter;
     5 import java.lang.reflect.Constructor;
     6 import java.lang.reflect.Method;
     7 import java.net.URL;
     8 import java.net.URLClassLoader;
     9 
    10 import javax.tools.JavaCompiler;
    11 import javax.tools.JavaCompiler.CompilationTask;
    12 import javax.tools.StandardJavaFileManager;
    13 import javax.tools.ToolProvider;
    14 
    15 public class Proxy {
    16 
    17     public static Object newProxyInstance(Class interfze) throws Exception {
    18         
    19         String rt = "
    
    ";
    20         
    21         //拼接"实现接口方法"的字符串
    22         String methodStr = "";
    23         for(Method m: interfze.getMethods() ){
    24             
    25             //取出方法的修饰符和返回值类型
    26             String [] parts = m.toString().replace("abstract ", "").split("\.");
    27             String [] parts2 = parts[0].split(" ");
    28             
    29             methodStr +=
    30             "@Override" + rt +
    31             parts2[0]+" "+parts2[1]+" "+m.getName()+"() {" + rt +
    32                 "System.out.println("Time Proxy start...........");" + rt +
    33                 "long start = System.currentTimeMillis();" + rt +
    34                 "m." + m.getName() + "();" + rt +
    35                 "long end = System.currentTimeMillis();" + rt +
    36                 "System.out.println("花费时间:"+(end - start));" + rt +
    37                 "System.out.println("Time Proxy end...........");" + rt +
    38             "}" ;
    39         }
    40         
    41         
    42         //动态代理文件的源码
    43         String str = 
    44         "package proxy;" + rt +
    45 
    46         "public class TankTimeProxy implements " + interfze.getName() + " {"+rt+
    47 
    48             "private " + interfze.getName() + " m;" + rt +
    49             
    50             "public TankTimeProxy(" + interfze.getName() + " m) {" + rt +
    51                 "this.m = m;" + rt +
    52             "}" + rt +
    53 
    54             methodStr + rt +
    55 
    56         "}" ;
    57         
    58         //把源码写到java文件里
    59         File file = new File(System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.java");
    60         FileWriter fw = new FileWriter(file);
    61         fw.write(str);
    62         fw.flush();
    63         fw.close();
    64         
    65         //编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误
    66         JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
    67         
    68         //文件管事器
    69         StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);
    70         
    71         //编译单元
    72         Iterable units = fileMgr.getJavaFileObjects(file);
    73         
    74         //编译任务
    75         CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);
    76         
    77         //编译
    78         t.call();    
    79         fileMgr.close();
    80         
    81         //把类load到内存里
    82         URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.class")};
    83         URLClassLoader uc = new URLClassLoader(urls);
    84         Class c = uc.loadClass("proxy.TankTimeProxy");
    85         
    86         //生成实例
    87         //return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
    88         Constructor ctr = c.getConstructor(interfze);
    89         return ctr.newInstance(new Tank());
    90     }
    91 }

    4.Client.java

     1 package proxy;
     2 
     3 import java.io.IOException;
     4 
     5 import org.junit.Test;
     6 
     7 public class Client {
     8 
     9     @Test
    10     public void testProxy() throws Exception{
    11         
    12         Movable m = (Movable)Proxy.newProxyInstance(Movable.class);
    13         m.move();
    14         m.stop();
    15         
    16     }
    17 }

    三、运行结果

  • 相关阅读:
    py-day1-2 python的循环语句
    B/S和C/S结构的区别
    php get_magic_quotes_gpc() addslashes()
    SqlHelper数据库访问类
    随滚动条滚动的居中div
    有关Repeater的事件
    Repeater的ItemCommand事件和ItemCreated事件,高手请跳过~
    温故而知新之数据库的分离和附加…高手请跳过….
    自己做的一个小功能~
    php什么是变量的数据类型
  • 原文地址:https://www.cnblogs.com/shamgod/p/4592359.html
Copyright © 2011-2022 走看看