模拟实现JDK动态代理Proxy

模拟实现JDK动态代理Proxy

  • 可以对任意的对象、任意的接口方法实现任意的代理

Handler接口

package cn.chen.proxy.compiler;

import java.lang.reflect.Method;

public interface InvocationHander {

    void invoke(Object o,Method method);

}

代理类实现Handler接口,编入自己的逻辑

package cn.chen.proxy.compiler;

import java.lang.reflect.Method;

public class TimeHander implements InvocationHander {

    private Object target;

    public TimeHander(Object target) {
        this.target = target;
    }

    @Override
    public void invoke(Object o,Method method) {
        long start = System.currentTimeMillis();
        System.out.println("开始:" + start);
        System.out.println(o.getClass().getName());
        try {
            method.invoke(target,new Object[]{});
        } catch (Exception e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("运行:" + (start - end));
    }

}


package cn.chen.proxy.compiler.test;

import cn.chen.proxy.compiler.InvocationHander;

import java.lang.reflect.Method;

public class TransacationHandler implements InvocationHander{

    private Object target;

    public TransacationHandler(Object target) {
        this.target = target;
    }

    @Override
    public void invoke(Object o, Method method) {
        System.out.println("Transaction start");
        try {
            method.invoke(target);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Transaction commit");
    }
}

Proxy产生新的代理类
JDK6的编译api

package cn.chen.proxy;

import cn.chen.proxy.compiler.InvocationHander;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Proxy {

    /**
     * 产生新的代理类
     * @return
     */
    public static Object newProxyInstance(Class infce, InvocationHander h) throws Exception {
        String methodStr = "";
        String rt = "\n";
        Method[] methods = infce.getMethods();

//        for(Method method : methods){
//            methodStr += "@Override" + rt +
//                    "public void " + method.getName() + "()" +"{"+rt +
//                    "        long start = System.currentTimeMillis();" + rt +
//                    "        System.out.println(\"开始:\" + start);" + rt +
//                    "        tank."+method.getName()+"();\n" +
//                    "        long end = System.currentTimeMillis();\n" +
//                    "        System.out.println(\"运行:\" + (start - end));\n" +
//                    "}";
//        }

        for(Method method : methods){
            methodStr += "@Override" + rt +
                    "public void " + method.getName() + "()" +"{"+rt +
                        "   try{" + rt +
                        "   Method method = "+ infce.getName() + ".class.getMethod(\""+ method.getName()+"\");" + rt +
                        "   h.invoke(this,method);" + rt +
                        "   }catch(Exception e){e.printStackTrace();}" +
                    "}";
        }


        String src = "package cn.chen.proxy.compiler;\n" +
                "import cn.chen.proxy.Moveable;\n" +
                "import java.lang.reflect.Method;\n" +
                "public class $Proxy1 implements " + infce.getName() +" {\n" +

                "    public $Proxy1(InvocationHander h) {\n" +
                "        this.h = h;" + rt +
                "    }" + rt +

                "   cn.chen.proxy.compiler.InvocationHander h;"+ rt+
                        methodStr + rt+
                "}";
        // /Users/chenxiaokang/Documents/IDEAProject/mianshi
//        System.out.println(System.getProperty("user.dir"));
        String fileName = System.getProperty("user.dir") + "/src/main/java/cn/chen/proxy/compiler/$Proxy1.java";
        File f = new File(fileName);
        FileWriter fw = new FileWriter(f);
        fw.write(src);
        fw.flush();
        fw.close();
    // 编译
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // com.sun.tools.javac.api.JavacTool
        //        System.out.println(compiler.getClass().getName());
        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null,null,null);
        Iterable units = fileMgr.getJavaFileObjects(fileName);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileMgr, null, null, null,units);
        task.call();
        fileMgr.close();

        //load into memory and create an instance
        URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir") + "/src/main/java")};
        URLClassLoader ul = new URLClassLoader(urls);
        Class c = ul.loadClass("cn.chen.proxy.compiler.$Proxy1");
        System.out.println(c);

        Constructor constructor = c.getConstructor(InvocationHander.class);
        Object m = constructor.newInstance(h);
        return m;
    }

}

中间生成的代理代码

package cn.chen.proxy.compiler;
import cn.chen.proxy.Moveable;
import java.lang.reflect.Method;
public class $Proxy1 implements cn.chen.proxy.Moveable {
    public $Proxy1(InvocationHander h) {
        this.h = h;
    }
   cn.chen.proxy.compiler.InvocationHander h;
@Override
public void move(){
   try{
   Method method = cn.chen.proxy.Moveable.class.getMethod("move");
   h.invoke(this,method);
   }catch(Exception e){e.printStackTrace();}}
}

测试

package cn.chen.proxy.compiler.test;

public interface UserMgr {

    void addUser();

}


package cn.chen.proxy.compiler.test;

public class UserMgrImpl implements UserMgr{
    @Override
    public void addUser() {
        System.out.println("1.插入记录到User表");
        System.out.println("2.做日志在另外一张表");
    }
}

package cn.chen.proxy.compiler.test;

import cn.chen.proxy.Proxy;
import cn.chen.proxy.compiler.InvocationHander;

public class Client {

    public static void main(String[] args) throws Exception {
        UserMgr userMgr = new UserMgrImpl();
        InvocationHander h = new TransacationHandler(userMgr);
        UserMgr u = (UserMgr) Proxy.newProxyInstance(UserMgr.class, h);
        u.addUser();
    }

}

package cn.chen.proxy.compiler;
import java.lang.reflect.Method;
public class $Proxy1 implements cn.chen.proxy.compiler.test.UserMgr {
    public $Proxy1(InvocationHander h) {
        this.h = h;
    }
   cn.chen.proxy.compiler.InvocationHander h;
@Override
public void addUser(){
   try{
   Method method = cn.chen.proxy.compiler.test.UserMgr.class.getMethod("addUser");
   h.invoke(this,method);
   }catch(Exception e){e.printStackTrace();}}
}


class cn.chen.proxy.compiler.$Proxy1
Transaction start
1.插入记录到User表
2.做日志在另外一张表
Transaction commit

Process finished with exit code 0

我们模拟了JDK动态代理的内部实现,接下来我们使用JDK提供的Proxy来实现动态代理:JDK提供的动态代理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值