美文网首页
代理模式

代理模式

作者: 什么都没有说 | 来源:发表于2018-05-31 18:49 被阅读0次

代理模式的作用:AOP、拦截器、解耦 ...

1. 静态代理:

2. 动态代理:

3. 自己手写动态代理:

  • 结构


    结构图
  • 代理类Proxy
package xin.zero2one.proxy.myproxy;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * Created by jundo on 2018/5/30.
 */
public class MyProxy {

    private final static String ln = "\r\n";

    public static Object newProxyInstance(MyClassLoader loader, Class<?>[] interfaces, MyInvocationHandler h){

        try {
            //生成$Proxy.java文件,只针对Car对象
            String src = generateSrc(interfaces);

            //将$Proxy.java保存到classpath
            String classpath = MyProxy.class.getResource("").getPath();
            File proxyFile = new File(classpath + "$Proxy0.java");
            FileWriter fw = new FileWriter(proxyFile);
            fw.write(src);
            fw.flush();
            fw.close();

            //编译$Proxy.java
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable<? extends JavaFileObject> iterable = manager.getJavaFileObjects(proxyFile);
            JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
            task.call();
            manager.close();

            //将$Proxy.java加载到内存中
            System.out.println("find class");
            Class<?> proxy0 = loader.findClass("$Proxy0");
            System.out.println("find ok");
            Constructor<?> constructor = proxy0.getConstructor(MyInvocationHandler.class);
            return constructor.newInstance(h);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private static String generateSrc(Class<?>[] interfaces){
        StringBuffer sb = new StringBuffer();
        sb.append("package xin.zero2one.proxy.myproxy;" + ln);
        sb.append("import xin.zero2one.bean.Car;" + ln);
        sb.append("import xin.zero2one.proxy.myproxy.MyInvocationHandler;" + ln);
        sb.append("import java.lang.reflect.Method;" + ln);
        sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + ln);
        sb.append("MyInvocationHandler h;" + ln);
        sb.append("public $Proxy0(MyInvocationHandler h) { " + ln);
        sb.append("this.h = h;");
        sb.append("}" + ln);
        for (Method m : interfaces[0].getMethods()){
            sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
            sb.append("try{" + ln);
            sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\",new Class[]{});" + ln);
            sb.append("this.h.invoke(this,m,null);" + ln);
            sb.append("}catch(Throwable e){" + ln);
            sb.append("e.printStackTrace();" + ln);
            sb.append("}");
            sb.append("}");
        }
        sb.append("}" + ln);
        return sb.toString();
    }
}

  • MyInvocationHandler
package xin.zero2one.proxy.myproxy;

import java.lang.reflect.Method;

/**
 * Created by jundo on 2018/5/30.
 */
public interface MyInvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
  • MyClassLoader
package xin.zero2one.proxy.myproxy;

import java.io.*;

/**
 * Created by jundo on 2018/5/30.
 */
public class MyClassLoader extends ClassLoader{

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String classpath = MyClassLoader.class.getResource("").getPath();
        String className = MyClassLoader.class.getPackage().getName() + "." + name;
        String filePath = name.replaceAll("\\.", "/");
        File classFile = new File(classpath, filePath + ".class");
        if (classFile.exists()) {
            FileInputStream fis = null;
            ByteArrayOutputStream out = null;
            try {
                fis = new FileInputStream(classFile);
                out = new ByteArrayOutputStream();
                byte[] bytes = new byte[1024];
                int len;
                while ((len = fis.read(bytes)) != -1) {
                    out.write(bytes, 0, len);
                }
                return defineClass(className, out.toByteArray(), 0, out.size());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        return null;
    }
}
  • 被代理接口Car
package xin.zero2one.bean;

/**
 * Created by jundo on 2018/5/29.
 */
public interface Car {

    void getCar();
}
  • Car实现类
package xin.zero2one.bean;

/**
 * Created by jundo on 2018/5/29.
 */
public class Tesla implements Car{
    @Override
    public void getCar() {
        System.out.println("get tesla");
    }
}
  • Car代理类
package xin.zero2one.proxy;

import xin.zero2one.bean.Car;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by jundo on 2018/5/29.
 */
public class CarProxy implements InvocationHandler{

    private Car car;

    public Object getInstance(Car car){
        this.car = car;
        Class<?> clazz = car.getClass();
        Class<?>[] interfaces = clazz.getInterfaces();
        Car obj = (Car) Proxy.newProxyInstance(clazz.getClassLoader(), interfaces, this);
        return obj;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("找车子啦");
        System.out.println(method == null);
        method.invoke(this.car,args);
        System.out.println("就决定是你了");
        return null;
    }
}
  • 测试类
package xin.zero2one.proxy.myproxy;

import xin.zero2one.bean.Car;
import xin.zero2one.bean.Tesla;

/**
 * Created by jundo on 2018/5/30.
 */
public class MyProxyTest {

    public static void main(String[] args) {
        MyCarProxy proxy = new MyCarProxy();
        Car car = (Car)proxy.getInstance(new Tesla());
        car.getCar();
    }
}

相关文章

  • 设计模式

    单例模式 模板方法模式 工厂模式 代理模式 静态代理 JDK动态代理

  • 设计模式

    单例模式 代理模式 静态代理 jdk动态代理 cglib动态代理 工厂模式 适配器模式 建造者模式 观察者模式

  • kube-proxy的3种模式

    userspace代理模式 iptables代理模式 IPVS代理模式 https://kubernetes.io...

  • 第4章 结构型模式-代理模式

    一、代理模式简介 二、代理模式3个角色 三、代理模式的优点 四、代理模式的实例(游戏代练)

  • 理解代理模式

    原创博客地址 简介 代理模式,也叫做委托模式,分为:静态代理动态代理 代理模式也是平时比较常用的设计模式之一,代理...

  • 结构型 代理模式(文末有项目连接)

    1:什么是代理模式 2:没用代理模式时的实例 3:使用代理模式将其解耦(静态代理) 3:使用代理模式将其解耦(动态...

  • 设计模式-动态代理模式

    之前介绍了代理模式,大家也都了解了代理模式,不过之前介绍的代理模式是静态代理,静态代理什么意思?静态代理指的是代理...

  • 代理模式

    一、什么是代理模式 代理模式(Proxy pattern):代理模式又叫委托模式,是为某个对象提供一个代理对象,并...

  • 设计模式之代理模式(Proxy模式)

    代理模式的引入 代理模式的实例程序 代理模式的分析 代理模式的引入 Proxy是代理人的意思,指的是代替别人进行工...

  • Java设计模式之代理模式

    Java设计模式之代理模式 代理模式 静态代理 动态代理 为什么需要代理 通过代理,我们能够不用知道委托人是谁,而...

网友评论

      本文标题:代理模式

      本文链接:https://www.haomeiwen.com/subject/jigqsftx.html