• 动态代理的使用和实现机制


    工作中很久没有接触动态代理,之前的学习也有些模糊,导致有些遗忘,这里记录下个人对动态代理的理解,如有读者发现问题多多指正吧。

    就java而言对于动态代理的支持多是以接口实现,其实现主要是通过java.lang.reflect.Proxy类,java.lang.reflect.InvocationHandler接口。Proxy类主要用于获取动态代理对象,InvocationHandler接口用来约束调用者实现。

    动态代理运行机制:

    Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法会返回一个代理对象类的实例。当程序执行时会通过反射机制动态的生成一个代理类,该类实现一个接口里的方法(也就是说代理类与被代理类有相同的接口),在该代理类里面有一个InvocationHandler类型的成员变量,也就是调用处理程序,通过调用处理程序来给被代理类增强功能。创建好代理类后就调用类加载器将该类加载到类存,然后再通过反射创建一个该代理类的实例对象。下面是具体实现:

    1.代理接口:Moveable.java
    
    package com.test;
    
    public interface Moveable {
    
           void move();
    
    }
    
    
    2.被代理对象:Tank.java
    package com.test;
    
    import java.util.Random;
    
    public class Tank implements Moveable {
    
        public void move() {
             System.out.println("Tank moving...");
             try {
                 Thread.sleep(new Random().nextInt(10000));
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
    
    }
    
    3.为被代理对象产生一个代理类对象,其中是想增加记录运行时间的功能
    
    package com.test;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    import javax.tools.JavaCompiler;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    import javax.tools.JavaCompiler.CompilationTask;
    
    public class Proxy {
         public static Object newProxyInstance(Class interfaces,InvocationHandler h)throws Exception{
             StringBuffer methodStr = new StringBuffer();
             String tr = "
    ";
             Method[] methods = interfaces.getMethods();
             //拼接代理类的方法
             for (Method method : methods) {
                 methodStr.append(
                 "    public "+ method.getReturnType()+ " " +method.getName()+"() {" + tr +
                 "        try {" + tr +
                 "            java.lang.reflect.Method md = " + interfaces.getName() + "." + "class.getMethod(""  + method.getName() + "");" + tr +
                 "            h.invoke(this,md);" + tr +
                 "        }catch(Exception e) {e.printStackTrace();}" + tr +
                 "    }" + tr
                 );
             }
    
             //拼接代理类
             String src = "package com.test;" + tr +
             "import com.test.Moveable;" + tr +
             "public class TimeProxy implements " + interfaces.getName() + " {" + tr +
             "    private com.test.InvocationHandler h;" + tr +
             "    public TimeProxy(com.test.InvocationHandler h) {" + tr +
             "        this.h = h;" + tr +
             "    }" + tr +
             methodStr.toString() + tr +
             "}";
             //创建代理类
             String fileName = System.getProperty("user.dir") + "/src/com/test/TimeProxy.java";
             File file = new File(fileName);
             FileWriter writer = new FileWriter(file);
             writer.write(src);
             writer.flush();
             writer.close();
             //编译
             JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
             StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
             Iterable units = fileMgr.getJavaFileObjects(fileName);
             CompilationTask ct = compiler.getTask(null, fileMgr, null, null, null, units);
             ct.call();
             fileMgr.close();
             //加载类到内存:
             Class c = ClassLoader.getSystemClassLoader().loadClass("com.test.TimeProxy");
             Constructor constructor = c.getConstructor(InvocationHandler.class); //得到参数为InvocationHandler类型的构造方法
             Object m = constructor.newInstance(h); //通过该构造方法得到实例
             return m;
    
         }
    }
    
    4.TankProxy.java
    
    package com.test;
    
    import java.lang.reflect.Method;
    
    public class TankProxy {
         public static <T> T getBean(final Object tank) throws Exception{
             return (T)Proxy.newProxyInstance(tank.getClass().getInterfaces()[0], new InvocationHandler(){
                 public void invoke(Object proxy, Method method) {
                     long start = System.currentTimeMillis();
                     System.out.println("start:"+start);
                     try {
                         method.invoke(tank, new Object[]{});
                     } catch (Exception e) {
                         e.printStackTrace();
                     }
                     long end = System.currentTimeMillis();
                     System.out.println("end:"+end);
                     System.out.println("time:"+(end-start));
                 }
    
             });
         }
    }
    
    5.测试程序:
    
    package com.test;
    
    import java.util.List;
    
    import com.extend.Tank2;
    import com.extend.Tank3;
    import com.juhe.LogProxy;
    import com.juhe.TimeProxy;
    
    public class Test {
         public static void main(String[] args) throws Exception {
             Tank tank = new Tank();
             Moveable m =  TankProxy.getBean(tank);
             m.move();
    
         }
    
    }
    
    
    
    执行该程序的结果为:
    start:1369121253400
    Tank moving...
    end:1369121260078
    time:6678
    
    
    
    动态生成的代理类的内容如下:
    
    package com.test;
    import com.test.Moveable;
    public class TimeProxy implements com.test.Moveable {
         private com.test.InvocationHandler h;
         public TimeProxy(com.test.InvocationHandler h) {
             this.h = h;
         }
         public void move() {
             try {
                 java.lang.reflect.Method md = com.test.Moveable.class.getMethod("move");
                 h.invoke(this,md);
             }catch(Exception e) {e.printStackTrace();}
         }
    
    }
  • 相关阅读:
    1 3
    linux常用命令
    linux的目录结构
    linux的shell编程
    linux的IP配置
    linux安装
    linux简介
    ubuntu16.04上系统管理服务和配置
    PXE
    RPC框架原理
  • 原文地址:https://www.cnblogs.com/bymcyc/p/8488986.html
Copyright © 2020-2023  润新知