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 = "\n\r";
    private static final String t = "\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

posted @ 2020-05-29 11:56  张艳涛&java  阅读(305)  评论(0编辑  收藏  举报