zoukankan      html  css  js  c++  java
  • No_1 手写Proxy

    手写动态代理主要原理:

    userDAO=(UserDAO)Proxy.newProxyinstance(classloader,interfaces[],new MyInvocationHandler(targer);

    userDAO.save();

    public class AppMain {
    //上课老师的代码
        public static void main(String[] args) {
    
            UserDAO userDAO = new UserDAO();
            Object proxyObject = newProxy(userDAO);
            IDAO idao = (IDAO) proxyObject;
            idao.save();
        }
    
        public static Object newProxy(Object target) {
            // 生成动态类,类的方法来之接口,得到Class对象
            /// class[]数组中放的是UserDAO的所有接口类信息
            Class[] interfaces = target.getClass().getInterfaces();
            // 需要类加载器
            ClassLoader classLoader = target.getClass().getClassLoader();
            // 回调myHandler
            MyInvocationHandler myHandler = new MyInvocationHandler(target);
    
            // 调用java动态处理框架
            Object proxyObject = Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler(target) {
    
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    // TODO Auto-generated method stub
                    System.out.println("日志");
                    return super.invoke(target, method, args);
                }
                
            });
            return proxyObject;
        }
    
        static class MyInvocationHandler implements InvocationHandler {
    
            Object target;
    
            public MyInvocationHandler(Object target) {
                super();
                this.target = target;
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("日志");
                method.invoke(target, args);
                return null;
            }
    
        }
    }

    1=. class ZProxy {  public Object newProxyinstance( classLoader, interfaces, new MyInvocationHandler(target){

              1.拼写字符串,public class MyProxy {   @1 有一个构造方法 接受handler; @2 调用方法query{  里面是handler.invoke(this,method,arges)} ,注意这个第一个参数是this对象;

    生成的动态代理对象          

    package com.jv.own;
     
    import com.jv.own.UserDao;
    import java.lang.reflect.Method;
     
    import com.jv.own.MyInvocationHandler;
     
    public class MyProxy implements UserDao{
     
        private MyInvocationHandler handler;
        public MyProxy(MyInvocationHandler handler){
            this.handler = handler;
        }
     
        public com.jv.own.User query(java.lang.String p1){
            try{
                Object[] args = new Object[]{p1};
                Method method = com.jv.own.UserDao.class.getMethod("query",Class.forName("java.lang.String"));
                return (com.jv.own.User)handler.invoke(this,method,args);
            }catch(Throwable e){
                return null;
            }
        }
    }

              2. 根据生成的MyProxy类,利用构造方法生成对象,同时传入handler对象;return constructors[0].newInstance(handler);

    URL[] urls = new URL[]{new URL("file:f\\projects\own\spring-framework-master\proxy\out\production\classes")};
     
            URLClassLoader urlClassLoader = new URLClassLoader(urls);
            Class clazz = urlClassLoader.loadClass("com.jv.own.MyProxy");
            //############################################实例化############################################
     
            //返回
            Constructor[] constructors = clazz.getConstructors();
            constructors[0].newInstance(handler);
            return constructors[0].newInstance(handler);

              3. done

    第一个类

    package com.jv.own;
    
    import java.io.FileWriter;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    
    import javax.tools.JavaCompiler;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    
    public class MyProxyUtil {
    
        private static final String l = "
    
    ";
        private static final String t = "	";
     
        public static Object newInstance(ClassLoader classLoader,Class[] interfaces,MyInvocationHandler handler) throws Exception{
            StringBuilder sb = new StringBuilder();
            StringBuilder sbImport = new StringBuilder();
            StringBuilder sbImplements = new StringBuilder();
            StringBuilder sbMethods = new StringBuilder();
     
            //############################################生成源代码############################################
            //包定义
            sb.append("package com.jv.own;").append(l+l);
            if(interfaces == null || interfaces.length==0){
                throw new Exception("接口不能为空");
            }
            //生成导入和implements
            for (Class anInterface : interfaces) {
                sbImport.append("import "+anInterface.getName()+";"+l);
                sbImplements.append(anInterface.getSimpleName()+",");
            }
            sbImport.append("import java.lang.reflect.Method;").append(l+l);
            sbImport.append("import com.jv.own.MyInvocationHandler;").append(l+l);
            sb.append(sbImport.toString());
            String temp = sbImplements.toString().substring(0,sbImplements.toString().lastIndexOf(","));
            //类定义
            sb.append("public class MyProxy implements ").append(temp).append("{").append(l).append(l);
            sb.append(t+"private MyInvocationHandler handler;").append(l);
            //构造函数
            sb.append(t+"public MyProxy(").append("MyInvocationHandler handler){").append(l);
            sb.append(t+t+"this.handler = handler;").append(l).append(t).append("}").append(l).append(l);
            //生成接口里面所有的
            for (Class anInterface : interfaces) {
                Method[] methods = anInterface.getMethods();
                for (Method method : methods) {
                    String parameter = "";
                    String parameterType = "";
                    int i = 1;
                    for(Class cl:method.getParameterTypes()){
                        parameter += cl.getName() + " p" + i++ +",";
                        parameterType += "Class.forName(""+cl.getTypeName()+"")"+",";
                    }
                    if(parameter!=null&&!parameter.equals("")) {
                        parameter = parameter.substring(0, parameter.lastIndexOf(","));
                        parameterType = parameterType.substring(0, parameterType.lastIndexOf(","));
                    }
                    sbMethods.append(t).append("public ").append(method.getReturnType().getName()).append(" ").append(method.getName())
                             .append("(").append(parameter).append("){").append(l+t+t);
                    sbMethods.append("try{").append(l+t+t+t);
                    String args = "Object[] args = new Object[]{";
                    for(int j=1;j<i;j++){
                        args += "p"+j+",";
                    }
                    args = args.substring(0,args.lastIndexOf(","))+"};";
                    sbMethods.append(args).append(l+t+t+t);
     
                    StringBuilder methodContent = new StringBuilder();
                    //methodContent.append("Method method = Class.forName(""+anInterface.getTypeName()+"").getMethod(""+method.getName()+"","+parameterType+");");
                    methodContent.append("Method method = "+anInterface.getName()+".class.getMethod(""+method.getName()+"","+parameterType+");");
                    sbMethods.append(methodContent.toString()).append(l+t+t+t);
     
                    if(method.getReturnType().getName().equals("void")){
                        sbMethods.append("handler.invoke(this,method,args);").append(l+t+t);
                    }else{
                        sbMethods.append("return "+"("+method.getReturnType().getName()+")"+"handler.invoke(this,method,args);").append(l+t+t);
                    }
                    sbMethods.append("}catch(Throwable e){"+l+t+t+t+"return null;"+l+t+t+"}"+l+t);
                    sbMethods.append("}").append(l);
                }
            }
            sb.append(sbMethods.toString());
     
            sb.append("}");
            System.out.println(sb.toString());
     
            //############################################将源代码写入磁盘文件############################################
            String filePath = MyProxyUtil.class.getResource("").getPath()  + "MyProxy.java";
            System.out.println(filePath);
            FileWriter fileWriter = new FileWriter(filePath);
            fileWriter.write(sb.toString());
            fileWriter.flush();
            fileWriter.close();
            //############################################编译源代码############################################
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = fileManager.getJavaFileObjects(filePath);
            JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable);
            task.call();
            fileManager.close();
            //############################################将文件通过URLClassLocader或者自定义ClassLoader进行加载############################################
            URL[] urls = new URL[]{new URL("file:f\\projects\own\spring-framework-master\proxy\out\production\classes")};
     
            URLClassLoader urlClassLoader = new URLClassLoader(urls);
            Class clazz = urlClassLoader.loadClass("com.jv.own.MyProxy");
            //############################################实例化############################################
     
            //返回
            Constructor[] constructors = clazz.getConstructors();
            constructors[0].newInstance(handler);
            return constructors[0].newInstance(handler);
        }
    }

    第二个handler接口

    package com.jv.own;
    
    import java.lang.reflect.Method;
    
    public interface MyInvocationHandler {
     
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable;
     
    }

    第三个主app

    package com.jv.own;
     
     
    public class TestMyProxy {
        public static void main(String[] args) {
            MyInvocationHandler handler = new MyOwnInvocationHandler(new UserDaoImpl());
            try {
                UserDao dao = (UserDao)MyProxyUtil.newInstance(com.jv.own.UserDao.class.getClassLoader(),new Class[]{UserDao.class},handler);
                dao.query("a");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    第四个接口

    package com.jv.own;
     
    public class User {
        private String userName;
     
        public String getUserName() {
            return userName;
        }
     
        public void setUserName(String userName) {
            this.userName = userName;
        }
    }
    ------------------------------
    package com.jv.own;
     
    public interface UserDao {
        User query(String name);
    }
    --------------------------------
    package com.jv.own;
     
    public class UserDaoImpl implements UserDao {
        @Override
        public User query(String name) {
            System.out.println("UserDaoImpl execute query");
            return null;
        }
    }

    自己的handler

    package com.jv.own;
     
    import java.lang.reflect.Method;
     
    public class MyOwnInvocationHandler implements MyInvocationHandler{
        private UserDao target;
        public MyOwnInvocationHandler(UserDao target){
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("invoke before");
            method.invoke(target,args);
            System.out.println("invoke after");
            return null;
        }
    }

     托管地址

     https://github.com/atzhangsan/common_projects.git

    atzhang5月29

  • 相关阅读:
    [转]自定义ASP.NET AJAX拖放功能示例程序:实现IDragSource和IDropTarget接口将商品拖放至购物车中
    MySQL远程连接不上的解决方法
    Office 2007无法修复、卸载、重装
    使用Outlook Connector收发HOTMAIL邮件
    U盘数据恢复
    ISA假死现象
    SharePoint Server 2007序列号
    IBM x3650安装笔记机柜支架及RAID
    在产品的价值中售后服务也不能忽略
    彩信增强MMS.IT 增强S60手机彩信功能
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/12986668.html
Copyright © 2011-2022 走看看