zoukankan      html  css  js  c++  java
  • JDK动态代理

    在上一篇博客中分析了一下JAVA设计模式中的代理模式,其中动态代理中,又有一个十分重要的JDK动态代理,这篇文章主要是分析JDK动态代理究竟是如何实现的。

    动态代理实现思路

    实现功能:通过Proxy的newProxyInstance返回代理对象。

    1. 声明一段源码(动态产生代理)。
    2. 编译源码(JDK Compiler API),产生新的类(代理类)。
    3. 将这个类load到内存中,产生一个新的对象(代理对象)。
    4. return代理对象。

    准备工作:

    1. 引入一个jar包commons-io-2.2.jar。
    2. 将项目中Build Path下的JRE换成JDK,因为JRE不支持编译。

    实例:

    首先,自定义一个接口InvocationHandler

    public interface InvocationHandler {
        
        public void invoke(Object o,Method m);
    
    }

    接着定义接口的实现类

    public class TimeHandler implements InvocationHandler {
        private Object target;
        public TimeHandler(Object target) {
            super();
            this.target = target;
        }
    
        @Override
        public void invoke(Object o, Method m){
            try {
                System.out.println("日志开始打印.....");
                m.invoke(target);
                System.out.println("日志结束打印......");
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    编写模拟动态代理实现的类

    public class Proxy {
        public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{
            //window下的换行符
            String rt = "
    ";
            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 model;" + rt +
                         "import java.lang.reflect.Method;" + rt +
                         "import model.InvocationHandler;" + rt +
                            "public class $Proxy0 implements " + infce.getName() + "{" + rt +
                                "private InvocationHandler h;" + rt +    
                                "public $Proxy0(InvocationHandler h) {" + rt +
                                    "super();" + rt +
                                    "this.h = h;" + rt +
                                "}" + rt +                    
                                methodStr + rt +
                            "}";
            //产生代理类的java文件
            String filename = System.getProperty("user.dir")+"/src/model/$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("model.$Proxy0");
            //根据构造器初始化,产生代理类
            Constructor ctr = c.getConstructor(InvocationHandler.class);
            return ctr.newInstance(h);
        }
    }

    最后编写测试类

    public class Test {
        /**
         * 测试类
         * */
        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();
        }
    }
  • 相关阅读:
    HDU 2844 Coins(多重背包)
    HDU 4540 威威猫系列故事——打地鼠(DP)
    Codeforces Round #236 (Div. 2)
    FZU 2140 Forever 0.5
    HDU 1171 Big Event in HDU(DP)
    HDU 1160 FatMouse's Speed(DP)
    ZOJ 3490 String Successor
    ZOJ 3609 Modular Inverse
    ZOJ 3603 Draw Something Cheat
    ZOJ 3705 Applications
  • 原文地址:https://www.cnblogs.com/libinhyq/p/9584262.html
Copyright © 2011-2022 走看看