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();
        }
    }
  • 相关阅读:
    N46期第一周作业
    备份MBR分区表,并破坏后修复
    预习作业(五)作业
    预习作业(四)作业
    通过v$sqlarea,v$sql查询最占用资源的查询
    ORACLE快速彻底Kill掉的会话
    HTML5中修改表单验证默认提示语句
    input正则 常用正则(备用)
    使用扫描枪扫描条码时字符识别写入缓慢问题(针对element-ui的el-input)优化
    JQuery经验汇总
  • 原文地址:https://www.cnblogs.com/libinhyq/p/9584262.html
Copyright © 2011-2022 走看看