美文网首页
动态代理的实现

动态代理的实现

作者: liangxifeng833 | 来源:发表于2017-07-07 20:03 被阅读41次

一.我对动态代理的理解

1.动态生成代理类java源文件
2.将代理类java源文件编译为代理类class字节码文件
3.将代理类class字节码文件 自动加载到内存中
4.将自动加载到内存的代理类class字节码进行实例化为 代理对象
5.有了代理对象,就可以使用代理对象中的方法调用被代理对象的方法了;

二.动态代理的实现流程

点击查看代码演示

1.编写接口MoveAble 有move方法

package proxy.statics;
/**
 * 移动接口
 * @author lxf
 *
 */
public interface MoveAble {
    public  void move();
}

2.编写被代理类Car实现MoveAble接口,并实现move方法写业务罗辑;

package proxy.statics;
import java.util.Random;
/**
 * 被代理类,汽车
 * @author lxf
 * @2017-07-06
 */
public class Car implements MoveAble {

    @Override
    public void move() {
        //System.out.println("被代理对象---我是汽车对象本身:"+this.getClass().getName());
       //实现开车
       try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽车行驶中...");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

3.编写InvocationHandler接口(包含myinvoke方法)
注意:这里的InvocationHandler并不是java.lang.refect包下面的InvocationHandler

package proxy.dynamic.custom;
import java.lang.reflect.Method;
/**
 * 事务处理接口
 * @author lxf
 *
 */
public interface InvocationHandler {
    /**
     * 参数:Object obj 属于代理对象
     * 参数:Method method 属于代理对象的方法
     */
    public void myinvoke(Object obj, Method method);
}

4.编写TimerHandler类实现自己InvocationHandler接口中的myinvoke方法(用来调用被代理对象的方法,还有其他额外的业务逻辑)

package proxy.dynamic.custom;
import java.lang.reflect.Method;
/**
 * 实现自己定义的事务处理接口proxy.dynamic.custom.InvocationHandler
 * @author lxf
 *
 */
public class TimerHandler implements  InvocationHandler {
    //代理对象
    private Object target;
   
    public TimerHandler(Object target) {
        super();
        this.target = target;
    }

    /**
     * 参数:Object obj 属于代理对象
     * 参数:Method method 属于代理对象的方法
     */
    @Override
    public void myinvoke(Object obj, Method method) {
        // TODO Auto-generated method stub
        try {
            //开始时间 " + br + 
            Long start = System.currentTimeMillis(); 
            System.out.println("汽车开始行驶...");
            method.invoke(target);
            //结束时间 " + br + 
            Long end = System.currentTimeMillis(); 
            System.out.println("汽车结束行驶...行驶话费了:" + (end-start) + "ms"); 
            //视频听到3-3 3:42秒
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}

3.编写生成代理类的类Proxy,它的主要功能是 一步骤 中的所有流程;

package proxy.dynamic.custom;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import org.apache.commons.io.FileUtils;
import javax.tools.JavaCompiler.CompilationTask;
import proxy.statics.Car;
import proxy.statics.MoveAble;
/**
 * 动态代理类
 * @author lxf
 * 参数:
 * Class 代理类和被代理类实现的接口
 *  InvocationHandler h 自己实现的事务处理器proxy.dynamic.custom.TimerHandler
 *
 */
public class Proxy {
    
    /**
     * 自己实现JDK生成动态代理类及对象
     * @param infce 接口class,有了接口就可以通过接口获取接口中定义的方法,为生成代理类而用
     * @param h 自己创建的proxy.dynamic.custom.InvocationHandler 事务处理器(处理主要业务罗辑)
     *       事务处理器中包含被代理对象Car,具体处理业务罗辑的代码
     * @return
     * @throws IOException
     */
    public static Object newProxyInstance(Class infce, InvocationHandler h) throws IOException
    {
        String br = "\n"; //换行符
        String methodStr = "";
        //获取接口中所有的方法,遍历组合为代理类的方法
        for(Method m : infce.getMethods()){
            methodStr += "  @Override" + br +
            "   public void " + m.getName() + "() {" + br +
            "  try{" + br +
            "  Method md = " + infce.getName() + ".class.getMethod(\"" 
                                        + m.getName() + "\");" + br +
            "  h.myinvoke(this,md);" +br+ 
            "  }catch(Exception e){ e.printStackTrace();}" + br +
            "   }" ;
        }
        
        /**
         * 动态代理类字符串
         */
        String str = 
        " package proxy.dynamic.custom; " + br + 
        " import proxy.dynamic.custom.InvocationHandler; " + br +
        "  import java.lang.reflect.Method;" + br +
        " public class $Proxy0  implements "+infce.getName()+"{ " + br + 
         "  private InvocationHandler h; " + br + 
         "   public $Proxy0( InvocationHandler h ) " + br + 
         "  { " + br + 
         "       this.h = h; " + br + 
         "  } " + br +
         methodStr + br +
        "}";
        
        /*
         * 自行实现动态代理的流程
         * 1. 动态生成代理类.java源文件
         */
        //获取当前项目路径,/home/lxf/workspaceEE/proxy
        String filename = System.getProperty("user.dir") + "/bin/proxy/dynamic/custom/$Proxy0.java";
        System.out.println(filename);
        File file = new File(filename);
        FileUtils.writeStringToFile(file, str);
        
        /*
         * 2. 将动态生成的代理类.java源文件编译为class字节码文件
         */
        //编译
        //拿到编译器
        JavaCompiler complier = ToolProvider.getSystemJavaCompiler();
        //文件管理者
        StandardJavaFileManager fileMgr = 
                complier.getStandardFileManager(null, null, null);
        //获取文件
        Iterable units = fileMgr.getJavaFileObjects(filename);
        //编译任务
        CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units);
        //进行编译
        t.call();
        fileMgr.close();
           
       /**
        * load到内存中
        */
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Class c;
        try {
            c = cl.loadClass("proxy.dynamic.custom.$Proxy0");
            //System.out.println(c.getName());
            //通过构造器返回代理对象
            Constructor ctr = c.getConstructor(InvocationHandler.class);
            return ctr.newInstance(h);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return null;
    }
}

4.测试

package proxy.dynamic.custom;
import java.io.IOException;
import proxy.statics.Car;
import proxy.statics.MoveAble;
/**
 * 测试自己实现JDK动态代理实现思路
 * @author lxf
 * @date 2017-07-07
 */
public class testMain {
    public static void main(String[] args) throws IOException
    {
        //实例化被代理类
        Car car = new Car();
        //实例化事务处理器
        InvocationHandler h = new TimerHandler(car);
        //生成代理对象
        MoveAble m = (MoveAble)Proxy.newProxyInstance(MoveAble.class,h);
        //调用代理对象的方法
        m.move();
    }    
}

执行结果:

/home/lxf/workspaceEE/proxy/bin/proxy/dynamic/custom/$Proxy0.java
汽车开始行驶...
汽车行驶中...
汽车结束行驶...行驶话费了:975ms

动态生成代理类/home/lxf/workspaceEE/proxy/bin/proxy/dynamic/custom/$Proxy0.java的代码如下:

 package proxy.dynamic.custom; 
 import proxy.dynamic.custom.InvocationHandler; 
  import java.lang.reflect.Method;
 public class $Proxy0  implements proxy.statics.MoveAble{ 
  private InvocationHandler h; 
   public $Proxy0( InvocationHandler h ) 
  { 
       this.h = h; 
  } 
  @Override
   public void move() {
  try{
  Method md = proxy.statics.MoveAble.class.getMethod("move");
  h.myinvoke(this,md);
  }catch(Exception e){ e.printStackTrace();}
   }
}

相关文章

网友评论

      本文标题:动态代理的实现

      本文链接:https://www.haomeiwen.com/subject/gnerhxtx.html