详解JDK的动态代理+实例理解

该文学习资源来自https://www.imooc.com/video/5063

引言:当有无数个代理类的话,传统做法要写100个代理类,显然这样子类会过于膨胀,那么有没有一种方法,可以动态产生代理,实现对不同类,不同方法的代理。

动态代理:JDK的动态代理,ca

在代理类和被代理类之间加入了InvocationHander的一个类,也叫事务处理器。

被代理类:

package com.imooc.jdkproxy;

import com.imooc.jdkproxy.Moveable;

import java.util.Random;

public class Car implements Moveable {

    @Override
    public void move() {
        //实现开车
        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽车行驶中....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

被代理类的方法:

package com.imooc.jdkproxy;

/**
 * Created by Administrator on 2018/9/4.
 */
public interface Moveable {
   void move();
}

事物处理器:

public class TimeHandler implements InvocationHandler{
    private Object target;
    public TimeHandler(Object target) {
        this.target = target;
    }

    //proxy,被代理对象;
    //method 被代理对象的方法;
    //方法的参数
     //
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startTime=System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        method.invoke(target);// target为被代理对象
        long endTime=System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:"+(endTime-startTime)+"毫秒!");
        return null;//该示例中car的move()没有返回值
    }
}

测试类:

package com.imooc.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * Created by Administrator on 2018/9/4.
 */
public class Test {
    public static  void main(String [] args){
        Car car=new Car();
        InvocationHandler h=new TimeHandler(car);
       Class<?> cls =car.getClass();
/**
 * loader  类加载器
 * interfaces  实现接口
 * h InvocationHandler
 */
        Moveable m=(Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),h);//生成动态代理类,返回的值都代理类,都实现了movable接口
                m.move();//调用返回动态代理的move方法


    }
}

 run:  在move方法的基础上,增加了时间的代理方法。

 


JDK动态的代理的原理和内部实现: 

 

procy:

package com.imooc.proxy;

import java.io.File;
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;

import org.apache.commons.io.FileUtils;
//定义一个静态方法,返回一个代理对象
//第一步声明一段源码
public class Proxy {
    //(Class infce)把我们需要实现的接口传递过来
    public static Object newProxyInstance(Class infce) throws Exception{
        String rt = "\r\n";
        String methodStr = "";//获取方法
        for(Method m : infce.getMethods()){
            methodStr += "	@Override" + rt +
                    "	public void " + m.getName() + "() {" + rt +
                    "		long starttime = System.currentTimeMillis();" + rt +
                    "		System.out.println(\"汽车开始行驶....\");" + rt +
                    "		m." + m.getName() + "();" + rt +
                    "		long endtime = System.currentTimeMillis();" + rt +
                    "		System.out.println(\"汽车结束行驶....  汽车行驶时间:\" " + rt +
                    "				+ (endtime - starttime) + \"毫秒!\");" + rt +
                    "	}" ;
        }

        String str =
                "package com.imooc.proxy;" + rt +
                        "public class $Proxy0 implements " + infce.getName() + " {" + rt +
                        "	public $Proxy0(" + infce.getName() + " m) {" + rt +
                        "		super();" + rt +
                        "		this.m = m;" + rt +
                        "	}" + rt +
                        "	private " + infce.getName() + " m;" + rt +
                        methodStr + rt +
                        "}" ;
        //先产生代理类的java文件,在对java文件进行编译
        String filename = System.getProperty("user.dir") +"/bin/com/imooc/proxy/$Proxy0.java";//文件的路径取当前应用所在的路径,然后放在bin目录下
        File file = new File(filename);
        FileUtils.writeStringToFile(file, str);//将这段源码生成到我们的java文件当中;

        //编译
        //得到当前系统的编译器
        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 = cl.loadClass("com.imooc.proxy.$Proxy0");//loader文件名
//产生代理对象
        Constructor ctr = c.getConstructor(infce);
        return ctr.newInstance(new Car());
    }




}

 测试类:

package com.imooc.proxy;


public class Client {

    /**
     * 测试类
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        Moveable m = (Moveable) Proxy.newProxyInstance(Moveable.class);//产生一个代理对象,并实现Moveable接口
        m.move();
    }

}

 这样子就好了,但是我们会发现以上代码中,业务逻辑是写死的,也就是我们要怎么做才能适用于任意类和任意方法呢?

--------即,我们需要在动态代理中添加 InvocationHandler;

package com.imooc.proxy;

import java.lang.reflect.Method;

/**
 * Created by Administrator on 2018/9/14.
 */
public interface InvocationHandler{
        public void invoke(Object o,Method m);//invoke 对某个对象的方法进行处理。
}

修改我们的proxy类:

package com.imooc.proxy;

import java.io.File;
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;

import org.apache.commons.io.FileUtils;

public class Proxy {

    @SuppressWarnings("unchecked")
    public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{
        String rt = "\r\n";
        String methodStr = "";
        for(Method m : infce.getMethods()){
            methodStr += "	@Override" + rt +
                    "	public void " + m.getName() + "() {" + rt +
                    "  try{" + rt +
                    "  Method md = " + infce.getName() + ".class.getMethod(\""
                    + m.getName() + "\");" + rt +
                    "  h.invoke(this,md);" +rt+
                    "  }catch(Exception e){ e.printStackTrace();}" + rt +
                    "	}" ;
        }

        String str =
                "package com.imooc.proxy;" + rt +
                        "import java.lang.reflect.Method;" + rt +
                        "import com.imooc.proxy.InvocationHandler;" +  rt+
                        "public class $Proxy0 implements " + infce.getName() + " {" + rt +
                        "	public $Proxy0(InvocationHandler h) {" + rt +
                        "		this.h = h;" + rt +
                        "	}" + rt +
                        "  private InvocationHandler h;" + rt+
                        methodStr + rt +
                        "}" ;
        //产生代理类的java文件
        String filename = System.getProperty("user.dir") +"/bin/com/imooc/proxy/$Proxy0.java";
        File file = new File(filename);
        FileUtils.writeStringToFile(file, str);

        //编译
        //拿到编译器
        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 = cl.loadClass("com.imooc.proxy.$Proxy0");

        Constructor ctr = c.getConstructor(InvocationHandler.class);
        return ctr.newInstance(h);
    }




}

 测试类:

package com.imooc.proxy;

public class Client {

    /**
     * 测试类
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        Car car = new Car();
        InvocationHandler h = new TimeHandler(car);
        Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class,h);
        m.move();
    }

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值